Devi vietare l'atomica per ottenere un valido supporto agli strumenti per i rilevatori di corsa?

3

Sembra che Helgrind tratti gli atomici allo stesso modo delle normali operazioni di lettura / scrittura. Quindi, l'uso di atomici comporterà molti falsi positivi.

Non so esattamente come ThreadSanitizer si occupa di atomica, ma ho trovato un metodo chiamato tsan_atomic32_load. Suppongo che sia in grado di distinguere tra l'atomica e le normali operazioni di lettura / scrittura.

In pratica, tuttavia, il modo migliore sembra essere quello di evitare l'atomica per poter usare gli strumenti per rilevare le condizioni di gara. Altrimenti, finisci con molti falsi positivi.

Esistono strumenti specializzati per verificare strutture di dati concorrenti, ad es. Spin . Anche se sembra potente, sembra essere fuori portata per le normali applicazioni.

In che modo i grandi progetti affrontano il problema dei falsi positivi? Disincentivano l'uso dell'atomica, usano i file di soppressione o semplicemente non si preoccupano dei rilevatori di razza?

    
posta Philipp Claßen 02.10.2013 - 16:32
fonte

1 risposta

1

Un approccio che non hai menzionato è quello di annotare esplicitamente il tuo codice per dire allo strumento che cosa si intende per codice di blocco / conteggio personalizzato. Helgrind ha un esempio di come farlo nel suo manuale :

It is also possible to mark up the effects of thread-safe reference counting using the ANNOTATE_HAPPENS_BEFORE, ANNOTATE_HAPPENS_AFTER and ANNOTATE_HAPPENS_BEFORE_FORGET_ALL, macros. Thread-safe reference counting using an atomically incremented/decremented refcount variable causes Helgrind problems because a one-to-zero transition of the reference count means the accessing thread has exclusive ownership of the associated resource (normally, a C++ object) and can therefore access it (normally, to run its destructor) without locking. Helgrind doesn't understand this, and markup is essential to avoid false positives.

Here are recommended guidelines for marking up thread safe reference counting in C++. You only need to mark up your release methods -- the ones which decrement the reference count. Given a class like this:

class MyClass {
   unsigned int mRefCount;

   void Release ( void ) {
      unsigned int newCount = atomic_decrement(&mRefCount);
      if (newCount == 0) {
         delete this;
      }
   }
}

the release method should be marked up as follows:

   void Release ( void ) {
      unsigned int newCount = atomic_decrement(&mRefCount);
      if (newCount == 0) {
         ANNOTATE_HAPPENS_AFTER(&mRefCount);
         ANNOTATE_HAPPENS_BEFORE_FORGET_ALL(&mRefCount);
         delete this;
      } else {
         ANNOTATE_HAPPENS_BEFORE(&mRefCount);
      }
   }

ThreadSanitizer dice :

ThreadSanitizer supports DynamicAnnotations which can make any tricky synchronization (including lock-less synchronization) to be ThreadSanitizer-friendly.

Per quanto riguarda lo stile di codifica e i grandi progetti:

  • Una ricerca di ANNOTATE_HAPPENS_BEFORE nella sorgente Chromium genera molti risultati (ad esempio questo codice refcount atomico ), quindi è sicuramente possibile che un grande progetto utilizzi questo approccio.
  • Mettere queste annotazioni nel tuo stile di codifica è probabilmente una buona idea se intendi utilizzare le primitive di sincronizzazione a mano.

Allo stesso tempo, dovendo utilizzare queste annotazioni molto indica che hai un sacco di codice di sincronizzazione del thread personalizzato, il che potrebbe essere di per sé negativo.

    
risposta data 21.01.2014 - 22:16
fonte

Leggi altre domande sui tag