1717#include < cstdint>
1818
1919#include " absl/base/config.h"
20- #include " absl/base/internal/spinlock .h"
20+ #include " absl/base/const_init .h"
2121#include " absl/container/inlined_vector.h"
2222#include " absl/debugging/stacktrace.h"
2323#include " absl/strings/internal/cord_internal.h"
@@ -224,21 +224,23 @@ class CordRepAnalyzer {
224224CordzInfo* CordzInfo::Head (const CordzSnapshot& snapshot) {
225225 ABSL_ASSERT (snapshot.is_snapshot ());
226226
227- // We can do an 'unsafe' load of 'head', as we are guaranteed that the
228- // instance it points to is kept alive by the provided CordzSnapshot, so we
229- // can simply return the current value using an acquire load.
227+ // We obtain the lock here as we must synchronize the first call into the list
228+ // with any concurrent 'Untrack()` operation to avoid any read in the list to
229+ // reorder before the observation of the thread 'untracking a cord' of the
230+ // delete queue being empty or not. After this all next observations are safe
231+ // as we have established all subsequent untracks will be queued for delete.
230232 // We do enforce in DEBUG builds that the 'head' value is present in the
231233 // delete queue: ODR violations may lead to 'snapshot' and 'global_list_'
232234 // being in different libraries / modules.
233- CordzInfo* head = global_list_.head . load (std::memory_order_acquire );
234- ABSL_ASSERT (snapshot.DiagnosticsHandleIsSafeToInspect (head));
235- return head;
235+ absl::MutexLock l ( global_list_.mutex );
236+ ABSL_ASSERT (snapshot.DiagnosticsHandleIsSafeToInspect (global_list_. head ));
237+ return global_list_. head ;
236238}
237239
238240CordzInfo* CordzInfo::Next (const CordzSnapshot& snapshot) const {
239241 ABSL_ASSERT (snapshot.is_snapshot ());
240242
241- // Similar to the 'Head()' function, we do not need a mutex here.
243+ // We do not need a lock here. See also comments in Head() .
242244 CordzInfo* next = ci_next_.load (std::memory_order_acquire);
243245 ABSL_ASSERT (snapshot.DiagnosticsHandleIsSafeToInspect (this ));
244246 ABSL_ASSERT (snapshot.DiagnosticsHandleIsSafeToInspect (next));
@@ -327,22 +329,21 @@ CordzInfo::~CordzInfo() {
327329}
328330
329331void CordzInfo::Track () {
330- SpinLockHolder l (list_->mutex );
331-
332- CordzInfo* const head = list_->head .load (std::memory_order_acquire);
332+ absl::MutexLock l (list_->mutex );
333+ CordzInfo* const head = list_->head ;
333334 if (head != nullptr ) {
334335 head->ci_prev_ .store (this , std::memory_order_release);
335336 }
336337 ci_next_.store (head, std::memory_order_release);
337- list_->head . store ( this , std::memory_order_release) ;
338+ list_->head = this ;
338339}
339340
340341void CordzInfo::Untrack () {
341342 ODRCheck ();
342343 {
343- SpinLockHolder l (list_->mutex );
344+ absl::MutexLock l (list_->mutex );
344345
345- CordzInfo* const head = list_->head . load (std::memory_order_acquire) ;
346+ CordzInfo* const head = list_->head ;
346347 CordzInfo* const next = ci_next_.load (std::memory_order_acquire);
347348 CordzInfo* const prev = ci_prev_.load (std::memory_order_acquire);
348349
@@ -356,7 +357,7 @@ void CordzInfo::Untrack() {
356357 prev->ci_next_ .store (next, std::memory_order_release);
357358 } else {
358359 ABSL_ASSERT (head == this );
359- list_->head . store (next, std::memory_order_release) ;
360+ list_->head = next ;
360361 }
361362 }
362363
0 commit comments