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 ...@@ -22,7 +22,7 @@ ABSL_NAMESPACE_BEGIN
namespace base_internal { namespace base_internal {
// Well known Abseil object types that have causality. // 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 // `TraceWait` and `TraceContinue` record the start and end of a potentially
// blocking wait operation on `object`. `object` typically represents a higher // blocking wait operation on `object`. `object` typically represents a higher
...@@ -47,14 +47,14 @@ void TraceObserved(const void* object, ObjectKind kind); ...@@ -47,14 +47,14 @@ void TraceObserved(const void* object, ObjectKind kind);
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
extern "C" { extern "C" {
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(const void* object, 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,
ObjectKind kind); 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); ObjectKind kind);
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(const void* object,
ObjectKind kind);
} // extern "C" } // extern "C"
......
...@@ -141,6 +141,7 @@ cc_library( ...@@ -141,6 +141,7 @@ cc_library(
"//absl/base:dynamic_annotations", "//absl/base:dynamic_annotations",
"//absl/base:malloc_internal", "//absl/base:malloc_internal",
"//absl/base:raw_logging_internal", "//absl/base:raw_logging_internal",
"//absl/base:tracing_internal",
"//absl/debugging:stacktrace", "//absl/debugging:stacktrace",
"//absl/debugging:symbolize", "//absl/debugging:symbolize",
"//absl/time", "//absl/time",
...@@ -177,6 +178,9 @@ cc_test( ...@@ -177,6 +178,9 @@ cc_test(
], ],
deps = [ deps = [
":synchronization", ":synchronization",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/base:tracing_internal",
"//absl/time", "//absl/time",
"@com_google_googletest//:gtest", "@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main", "@com_google_googletest//:gtest_main",
......
...@@ -113,6 +113,7 @@ absl_cc_library( ...@@ -113,6 +113,7 @@ absl_cc_library(
absl::stacktrace absl::stacktrace
absl::symbolize absl::symbolize
absl::time absl::time
absl::tracing_internal
Threads::Threads Threads::Threads
PUBLIC PUBLIC
) )
...@@ -140,6 +141,7 @@ absl_cc_test( ...@@ -140,6 +141,7 @@ absl_cc_test(
DEPS DEPS
absl::synchronization absl::synchronization
absl::time absl::time
absl::tracing_internal
GTest::gmock_main GTest::gmock_main
) )
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <atomic> #include <atomic>
#include "absl/base/internal/raw_logging.h" #include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/tracing.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN ABSL_NAMESPACE_BEGIN
...@@ -40,6 +41,7 @@ bool BlockingCounter::DecrementCount() { ...@@ -40,6 +41,7 @@ bool BlockingCounter::DecrementCount() {
ABSL_RAW_CHECK(count >= 0, ABSL_RAW_CHECK(count >= 0,
"BlockingCounter::DecrementCount() called too many times"); "BlockingCounter::DecrementCount() called too many times");
if (count == 0) { if (count == 0) {
base_internal::TraceSignal(this, TraceObjectKind());
MutexLock l(&lock_); MutexLock l(&lock_);
done_ = true; done_ = true;
return true; return true;
...@@ -48,19 +50,23 @@ bool BlockingCounter::DecrementCount() { ...@@ -48,19 +50,23 @@ bool BlockingCounter::DecrementCount() {
} }
void BlockingCounter::Wait() { 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, // only one thread may call Wait(). To support more than one thread,
// implement a counter num_to_exit, like in the Barrier class. // implement a counter num_to_exit, like in the Barrier class.
ABSL_RAW_CHECK(num_waiting_ == 0, "multiple threads called Wait()"); ABSL_RAW_CHECK(num_waiting_ == 0, "multiple threads called Wait()");
num_waiting_++; 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 // At this point, we know that all threads executing DecrementCount
// will not touch this object again. // will not touch this object again.
// Therefore, the thread calling this method is free to delete the object // Therefore, the thread calling this method is free to delete the object
// after we return from this method. // after we return from this method.
}
base_internal::TraceContinue(this, TraceObjectKind());
} }
ABSL_NAMESPACE_END ABSL_NAMESPACE_END
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <atomic> #include <atomic>
#include "absl/base/internal/tracing.h"
#include "absl/base/thread_annotations.h" #include "absl/base/thread_annotations.h"
#include "absl/synchronization/mutex.h" #include "absl/synchronization/mutex.h"
...@@ -89,6 +90,11 @@ class BlockingCounter { ...@@ -89,6 +90,11 @@ class BlockingCounter {
void Wait(); void Wait();
private: private:
// Convenience helper to reduce verbosity at call sites.
static inline constexpr base_internal::ObjectKind TraceObjectKind() {
return base_internal::ObjectKind::kBlockingCounter;
}
Mutex lock_; Mutex lock_;
std::atomic<int> count_; std::atomic<int> count_;
int num_waiting_ ABSL_GUARDED_BY(lock_); int num_waiting_ ABSL_GUARDED_BY(lock_);
......
...@@ -15,9 +15,13 @@ ...@@ -15,9 +15,13 @@
#include "absl/synchronization/blocking_counter.h" #include "absl/synchronization/blocking_counter.h"
#include <thread> // NOLINT(build/c++11) #include <thread> // NOLINT(build/c++11)
#include <tuple>
#include <vector> #include <vector>
#include "gtest/gtest.h" #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/clock.h"
#include "absl/time/time.h" #include "absl/time/time.h"
...@@ -76,5 +80,67 @@ TEST(BlockingCounterTest, WaitNegativeInitialCount) { ...@@ -76,5 +80,67 @@ TEST(BlockingCounterTest, WaitNegativeInitialCount) {
#endif #endif
} // namespace } // 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 ABSL_NAMESPACE_END
} // namespace absl } // 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