Commit 034f8d05 by Martijn Vels Committed by Copybara-Service

Add tracing annotations to absl::BlockingCounter

PiperOrigin-RevId: 656010740
Change-Id: I99ef6f18502a0cb2c363c805ae5f9a9a42bd3b41
parent 9a0743ac
......@@ -22,7 +22,7 @@ ABSL_NAMESPACE_BEGIN
namespace base_internal {
// Well known Abseil object types that have causality.
enum class ObjectKind { kUnknown };
enum class ObjectKind { kUnknown, kBlockingCounter };
// `TraceWait` and `TraceContinue` record the start and end of a potentially
// blocking wait operation on `object`. `object` typically represents a higher
......@@ -47,14 +47,14 @@ void TraceObserved(const void* object, ObjectKind kind);
// ---------------------------------------------------------------------------
extern "C" {
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(const void* object,
ObjectKind kind);
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(const void* object,
ObjectKind kind);
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(const void* object,
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(const void* object,
ObjectKind kind);
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(const void* object,
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(const void* object,
ObjectKind kind);
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(const void* object,
ObjectKind kind);
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(const void* object,
ObjectKind kind);
} // extern "C"
......
......@@ -141,6 +141,7 @@ cc_library(
"//absl/base:dynamic_annotations",
"//absl/base:malloc_internal",
"//absl/base:raw_logging_internal",
"//absl/base:tracing_internal",
"//absl/debugging:stacktrace",
"//absl/debugging:symbolize",
"//absl/time",
......@@ -177,6 +178,9 @@ cc_test(
],
deps = [
":synchronization",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/base:tracing_internal",
"//absl/time",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
......
......@@ -113,6 +113,7 @@ absl_cc_library(
absl::stacktrace
absl::symbolize
absl::time
absl::tracing_internal
Threads::Threads
PUBLIC
)
......@@ -140,6 +141,7 @@ absl_cc_test(
DEPS
absl::synchronization
absl::time
absl::tracing_internal
GTest::gmock_main
)
......
......@@ -17,6 +17,7 @@
#include <atomic>
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/tracing.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
......@@ -40,6 +41,7 @@ bool BlockingCounter::DecrementCount() {
ABSL_RAW_CHECK(count >= 0,
"BlockingCounter::DecrementCount() called too many times");
if (count == 0) {
base_internal::TraceSignal(this, TraceObjectKind());
MutexLock l(&lock_);
done_ = true;
return true;
......@@ -48,19 +50,23 @@ bool BlockingCounter::DecrementCount() {
}
void BlockingCounter::Wait() {
MutexLock l(&this->lock_);
base_internal::TraceWait(this, TraceObjectKind());
{
MutexLock l(&this->lock_);
// only one thread may call Wait(). To support more than one thread,
// implement a counter num_to_exit, like in the Barrier class.
ABSL_RAW_CHECK(num_waiting_ == 0, "multiple threads called Wait()");
num_waiting_++;
// only one thread may call Wait(). To support more than one thread,
// implement a counter num_to_exit, like in the Barrier class.
ABSL_RAW_CHECK(num_waiting_ == 0, "multiple threads called Wait()");
num_waiting_++;
this->lock_.Await(Condition(IsDone, &this->done_));
this->lock_.Await(Condition(IsDone, &this->done_));
// At this point, we know that all threads executing DecrementCount
// will not touch this object again.
// Therefore, the thread calling this method is free to delete the object
// after we return from this method.
// At this point, we know that all threads executing DecrementCount
// will not touch this object again.
// Therefore, the thread calling this method is free to delete the object
// after we return from this method.
}
base_internal::TraceContinue(this, TraceObjectKind());
}
ABSL_NAMESPACE_END
......
......@@ -22,6 +22,7 @@
#include <atomic>
#include "absl/base/internal/tracing.h"
#include "absl/base/thread_annotations.h"
#include "absl/synchronization/mutex.h"
......@@ -89,6 +90,11 @@ class BlockingCounter {
void Wait();
private:
// Convenience helper to reduce verbosity at call sites.
static inline constexpr base_internal::ObjectKind TraceObjectKind() {
return base_internal::ObjectKind::kBlockingCounter;
}
Mutex lock_;
std::atomic<int> count_;
int num_waiting_ ABSL_GUARDED_BY(lock_);
......
......@@ -15,9 +15,13 @@
#include "absl/synchronization/blocking_counter.h"
#include <thread> // NOLINT(build/c++11)
#include <tuple>
#include <vector>
#include "gtest/gtest.h"
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/tracing.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
......@@ -76,5 +80,67 @@ TEST(BlockingCounterTest, WaitNegativeInitialCount) {
#endif
} // namespace
#if ABSL_HAVE_ATTRIBUTE_WEAK
namespace base_internal {
namespace {
using TraceRecord = std::tuple<const void*, ObjectKind>;
thread_local TraceRecord tls_signal;
thread_local TraceRecord tls_wait;
thread_local TraceRecord tls_continue;
} // namespace
// Strong extern "C" implementation.
extern "C" {
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(const void* object,
ObjectKind kind) {
tls_wait = {object, kind};
}
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(const void* object,
ObjectKind kind) {
tls_continue = {object, kind};
}
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(const void* object,
ObjectKind kind) {
tls_signal = {object, kind};
}
} // extern "C"
TEST(BlockingCounterTest, TracesSignal) {
BlockingCounter counter(2);
tls_signal = {};
counter.DecrementCount();
EXPECT_EQ(tls_signal, TraceRecord(nullptr, ObjectKind::kUnknown));
tls_signal = {};
counter.DecrementCount();
EXPECT_EQ(tls_signal, TraceRecord(&counter, ObjectKind::kBlockingCounter));
}
TEST(BlockingCounterTest, TracesWaitContinue) {
BlockingCounter counter(1);
counter.DecrementCount();
tls_wait = {};
tls_continue = {};
counter.Wait();
EXPECT_EQ(tls_wait, TraceRecord(&counter, ObjectKind::kBlockingCounter));
EXPECT_EQ(tls_continue, TraceRecord(&counter, ObjectKind::kBlockingCounter));
}
} // namespace base_internal
#endif // ABSL_HAVE_ATTRIBUTE_WEAK
ABSL_NAMESPACE_END
} // namespace absl
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment