summaryrefslogtreecommitdiff
path: root/absl/strings/internal/cordz_info.cc
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2021-04-27 09:11:54 -0700
committerGravatar Derek Mauro <dmauro@google.com>2021-04-27 16:35:21 +0000
commita5167f986b82e9a7535ee710e87e53cf4c8ef2a8 (patch)
tree05455a5490740b560cdd69550bd2844ecacd2ee2 /absl/strings/internal/cordz_info.cc
parentd96e287417766deddbff2d01b96321288c59491e (diff)
Export of internal Abseil changes
-- f6fbb03bff276e72123e8590519079e87732ae62 by Abseil Team <absl-team@google.com>: Replace static absl::Mutex with SpinLock in absl::Cords to avoid static initializers by absl::Mutex destructors PiperOrigin-RevId: 370694199 -- 654b7d9edfdc24f226990b2b46cbf91451a1d92a by Martijn Vels <mvels@google.com>: Implement global data for CordzInfo in an ODR hardened way This change puts the global data into a global list structure, and stores a reference to the global list in the handle itself. This hardens the implementation against ODR violations where info pointers are crossing dynamic library boundaries which are privately loaded. PiperOrigin-RevId: 370673045 -- 712dba768e66ee2ba85d6010829c617cd2af6ba7 by Martijn Vels <mvels@google.com>: Intrument Cord::operator= for Cordz PiperOrigin-RevId: 370659149 -- c0b347a2289e151b72680269332e264b8fa989c0 by Matt Kulukundis <kfm@google.com>: Fix test guards for ABSL_ATTRIBUTE_RETURNS_NONNULL PiperOrigin-RevId: 370594807 -- c2bedaa3472ef223f907de2604f9b9b58852ec5f by Martijn Vels <mvels@google.com>: Add new Cordz instrumentation on GetAppendRegion. PiperOrigin-RevId: 370587761 -- 84fbfcc852697d509f6094482b86e84743a6b331 by Martijn Vels <mvels@google.com>: Add instrumentation on Cord::Apppend(string_view) PiperOrigin-RevId: 370576590 -- 9e077390b8ca2239e1cb7bfbe1d5a04f2fc11d30 by Abseil Team <absl-team@google.com>: Google-internal changes only. PiperOrigin-RevId: 370558424 -- fb53c149eb2364ea34e3a67235f873866618b8ac by Matt Kulukundis <kfm@google.com>: Update config.h macros with a few useful helpers to simplify version checking PiperOrigin-RevId: 370557684 -- abf8142e99b9ff7e15f6528a357f1005461950b0 by Martijn Vels <mvels@google.com>: clang-format cord PiperOrigin-RevId: 370549371 -- e555985eabe63fcf0e980e9c433dd84caffec191 by Martijn Vels <mvels@google.com>: Add MaybeUntrackCord() function This function is near identical to the old UntrackCord() but allows info to be null, moving the cord.is_profiled() branch into CordzInfo. PiperOrigin-RevId: 370528447 -- 3883538efe4601f7864bda70a50d868bb383c63b by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 370503186 -- a9514b65542fde1bc73584e6f3c1c4b3a05f215f by Derek Mauro <dmauro@google.com>: Add -Winvalid-constexpr to warning options for LLVM PiperOrigin-RevId: 370455171 -- d8a3966de2cf15a2dc28e17e49a3d27d205eca92 by Martijn Vels <mvels@google.com>: Add naive UniqueGenerator<T, kMaxValues, ...> to avoid flakes from dup random values. PiperOrigin-RevId: 370179772 -- 46d0caa1a12b68a5998d4f919e20f0f83b9286f8 by Martijn Vels <mvels@google.com>: Add new Cordz instrumentation on PrependTree. PiperOrigin-RevId: 370138969 GitOrigin-RevId: f6fbb03bff276e72123e8590519079e87732ae62 Change-Id: Ifa4c00a5c7b01198ee367a3253bea6b66612135e
Diffstat (limited to 'absl/strings/internal/cordz_info.cc')
-rw-r--r--absl/strings/internal/cordz_info.cc78
1 files changed, 43 insertions, 35 deletions
diff --git a/absl/strings/internal/cordz_info.cc b/absl/strings/internal/cordz_info.cc
index d2200680..0461ec46 100644
--- a/absl/strings/internal/cordz_info.cc
+++ b/absl/strings/internal/cordz_info.cc
@@ -15,6 +15,7 @@
#include "absl/strings/internal/cordz_info.h"
#include "absl/base/config.h"
+#include "absl/base/internal/spinlock.h"
#include "absl/debugging/stacktrace.h"
#include "absl/strings/internal/cord_internal.h"
#include "absl/strings/internal/cordz_handle.h"
@@ -27,22 +28,34 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
+using ::absl::base_internal::SpinLockHolder;
+
constexpr int CordzInfo::kMaxStackDepth;
-ABSL_CONST_INIT std::atomic<CordzInfo*> CordzInfo::ci_head_{nullptr};
-ABSL_CONST_INIT absl::Mutex CordzInfo::ci_mutex_(absl::kConstInit);
+ABSL_CONST_INIT CordzInfo::List CordzInfo::global_list_{absl::kConstInit};
CordzInfo* CordzInfo::Head(const CordzSnapshot& snapshot) {
ABSL_ASSERT(snapshot.is_snapshot());
- ABSL_ASSERT(snapshot.DiagnosticsHandleIsSafeToInspect(ci_head_unsafe()));
- return ci_head_unsafe();
+
+ // We can do an 'unsafe' load of 'head', as we are guaranteed that the
+ // instance it points to is kept alive by the provided CordzSnapshot, so we
+ // can simply return the current value using an acquire load.
+ // We do enforce in DEBUG builds that the 'head' value is present in the
+ // delete queue: ODR violations may lead to 'snapshot' and 'global_list_'
+ // being in different libraries / modules.
+ CordzInfo* head = global_list_.head.load(std::memory_order_acquire);
+ ABSL_ASSERT(snapshot.DiagnosticsHandleIsSafeToInspect(head));
+ return head;
}
CordzInfo* CordzInfo::Next(const CordzSnapshot& snapshot) const {
ABSL_ASSERT(snapshot.is_snapshot());
+
+ // Similar to the 'Head()' function, we do not need a mutex here.
+ CordzInfo* next = ci_next_.load(std::memory_order_acquire);
ABSL_ASSERT(snapshot.DiagnosticsHandleIsSafeToInspect(this));
- ABSL_ASSERT(snapshot.DiagnosticsHandleIsSafeToInspect(ci_next_unsafe()));
- return ci_next_unsafe();
+ ABSL_ASSERT(snapshot.DiagnosticsHandleIsSafeToInspect(next));
+ return next;
}
void CordzInfo::TrackCord(InlineData& cord, MethodIdentifier method) {
@@ -63,14 +76,6 @@ void CordzInfo::TrackCord(InlineData& cord, const InlineData& src,
cordz_info->Track();
}
-void CordzInfo::UntrackCord(CordzInfo* cordz_info) {
- assert(cordz_info);
- if (cordz_info) {
- cordz_info->Untrack();
- CordzHandle::Delete(cordz_info);
- }
-}
-
CordzInfo::MethodIdentifier CordzInfo::GetParentMethod(const CordzInfo* src) {
if (src == nullptr) return MethodIdentifier::kUnknown;
return src->parent_method_ != MethodIdentifier::kUnknown ? src->parent_method_
@@ -110,14 +115,14 @@ CordzInfo::~CordzInfo() {
}
void CordzInfo::Track() {
- absl::MutexLock l(&ci_mutex_);
+ SpinLockHolder l(&list_->mutex);
- CordzInfo* const head = ci_head_.load(std::memory_order_acquire);
+ CordzInfo* const head = list_->head.load(std::memory_order_acquire);
if (head != nullptr) {
head->ci_prev_.store(this, std::memory_order_release);
}
ci_next_.store(head, std::memory_order_release);
- ci_head_.store(this, std::memory_order_release);
+ list_->head.store(this, std::memory_order_release);
}
void CordzInfo::Untrack() {
@@ -128,24 +133,28 @@ void CordzInfo::Untrack() {
rep_ = nullptr;
}
- absl::MutexLock l(&ci_mutex_);
-
- CordzInfo* const head = ci_head_.load(std::memory_order_acquire);
- CordzInfo* const next = ci_next_.load(std::memory_order_acquire);
- CordzInfo* const prev = ci_prev_.load(std::memory_order_acquire);
-
- if (next) {
- ABSL_ASSERT(next->ci_prev_.load(std::memory_order_acquire) == this);
- next->ci_prev_.store(prev, std::memory_order_release);
- }
- if (prev) {
- ABSL_ASSERT(head != this);
- ABSL_ASSERT(prev->ci_next_.load(std::memory_order_acquire) == this);
- prev->ci_next_.store(next, std::memory_order_release);
- } else {
- ABSL_ASSERT(head == this);
- ci_head_.store(next, std::memory_order_release);
+ ODRCheck();
+ {
+ SpinLockHolder l(&list_->mutex);
+
+ CordzInfo* const head = list_->head.load(std::memory_order_acquire);
+ CordzInfo* const next = ci_next_.load(std::memory_order_acquire);
+ CordzInfo* const prev = ci_prev_.load(std::memory_order_acquire);
+
+ if (next) {
+ ABSL_ASSERT(next->ci_prev_.load(std::memory_order_acquire) == this);
+ next->ci_prev_.store(prev, std::memory_order_release);
+ }
+ if (prev) {
+ ABSL_ASSERT(head != this);
+ ABSL_ASSERT(prev->ci_next_.load(std::memory_order_acquire) == this);
+ prev->ci_next_.store(next, std::memory_order_release);
+ } else {
+ ABSL_ASSERT(head == this);
+ list_->head.store(next, std::memory_order_release);
+ }
}
+ CordzHandle::Delete(this);
}
void CordzInfo::Lock(MethodIdentifier method)
@@ -163,7 +172,6 @@ void CordzInfo::Unlock() ABSL_UNLOCK_FUNCTION(mutex_) {
mutex_.Unlock();
if (!tracked) {
Untrack();
- CordzHandle::Delete(this);
}
}