Move `absl::MutexLock sample_lock` out of the global graveyard critical section. PiperOrigin-RevId: 985732017 Change-Id: I3e31f60efa867da97e0d833b7dfc3e0a6870c801
diff --git a/absl/profiling/internal/sample_recorder.h b/absl/profiling/internal/sample_recorder.h index 8663d6c..0d14027 100644 --- a/absl/profiling/internal/sample_recorder.h +++ b/absl/profiling/internal/sample_recorder.h
@@ -169,29 +169,23 @@ template <typename T> template <typename... Targs> T* SampleRecorder<T>::PopDead(Targs... args) { - T* sample; - { - absl::MutexLock graveyard_lock(graveyard_.init_mu); + absl::ReleasableMutexLock graveyard_lock(graveyard_.init_mu); - // The list is circular, so eventually it collapses down to - // graveyard_.dead == &graveyard_ - // when it is empty. - sample = graveyard_.dead; - if (sample == &graveyard_) return nullptr; + // The list is circular, so eventually it collapses down to + // graveyard_.dead == &graveyard_ + // when it is empty. + T* sample = graveyard_.dead; + if (sample == &graveyard_) return nullptr; - graveyard_.dead = ABSL_TS_UNCHECKED_READ(sample->dead); - // Release the global graveyard lock early, before the potentially slow - // preparation. - } - // `sample` is detached from the graveyard and will not be used in PopDead. - // SampleRecorder<T>::Iterate will acquire per sample lock, so there will be - // no data race either. absl::MutexLock sample_lock(sample->init_mu); - // Note: consider PrepareForSampling out of the lock. - // Currently many clients have PrepareForSampling marked as - // ABSL_EXCLUSIVE_LOCKS_REQUIRED. - sample->PrepareForSampling(std::forward<Targs>(args)...); + graveyard_.dead = sample->dead; + // Release the global graveyard lock early, before the potentially slow + // preparation. + graveyard_lock.Release(); + // Prepare the sample while still holding the per-sample lock. + // `Iterate` will wait for the lock to be released. sample->dead = nullptr; + sample->PrepareForSampling(std::forward<Targs>(args)...); return sample; }