OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 // This file defines dynamic annotations for use with dynamic analysis |
| 6 // tool such as valgrind, PIN, etc. |
| 7 // |
| 8 // Dynamic annotation is a source code annotation that affects |
| 9 // the generated code (that is, the annotation is not a comment). |
| 10 // Each such annotation is attached to a particular |
| 11 // instruction and/or to a particular object (address) in the program. |
| 12 // |
| 13 // The annotations that should be used by users are macros in all upper-case |
| 14 // (e.g., ANNOTATE_NEW_MEMORY). |
| 15 // |
| 16 // Actual implementation of these macros may differ depending on the |
| 17 // dynamic analysis tool being used. |
| 18 // |
| 19 // This file supports the following dynamic analysis tools: |
| 20 // - None (NDEBUG is defined). |
| 21 // Macros are defined empty. |
| 22 // - ThreadSanitizer (NDEBUG is not defined). |
| 23 // Macros are defined as calls to non-inlinable empty functions |
| 24 // that are intercepted by ThreadSanitizer. |
| 25 // |
| 26 #ifndef BASE_DYNAMIC_ANNOTATIONS_H_ |
| 27 #define BASE_DYNAMIC_ANNOTATIONS_H_ |
| 28 |
| 29 // All the annotation macros are in effect only in debug mode. |
| 30 #ifndef NDEBUG |
| 31 // Debug build. |
| 32 |
| 33 // ------------------------------------------------------------- |
| 34 // Annotations useful when implementing condition variables such as CondVar, |
| 35 // using conditional critical sections (Await/LockWhen) and when constructing |
| 36 // user-defined synchronization mechanisms. |
| 37 // |
| 38 // The annotations ANNOTATE_HAPPENS_BEFORE() and ANNOTATE_HAPPENS_AFTER() can |
| 39 // be used to define happens-before arcs in user-defined synchronization |
| 40 // mechanisms: the race detector will infer an arc from the former to the |
| 41 // latter when they share the same argument pointer. |
| 42 // |
| 43 // Example 1 (reference counting): |
| 44 // |
| 45 // void Unref() { |
| 46 // ANNOTATE_HAPPENS_BEFORE(&refcount_); |
| 47 // if (AtomicDecrementByOne(&refcount_) == 0) { |
| 48 // ANNOTATE_HAPPENS_AFTER(&refcount_); |
| 49 // delete this; |
| 50 // } |
| 51 // } |
| 52 // |
| 53 // Example 2 (message queue): |
| 54 // |
| 55 // void MyQueue::Put(Type *e) { |
| 56 // MutexLock lock(&mu_); |
| 57 // ANNOTATE_HAPPENS_BEFORE(e); |
| 58 // PutElementIntoMyQueue(e); |
| 59 // } |
| 60 // |
| 61 // Type *MyQueue::Get() { |
| 62 // MutexLock lock(&mu_); |
| 63 // Type *e = GetElementFromMyQueue(); |
| 64 // ANNOTATE_HAPPENS_AFTER(e); |
| 65 // return e; |
| 66 // } |
| 67 // |
| 68 // Note: when possible, please use the existing reference counting and message |
| 69 // queue implementations instead of inventing new ones. |
| 70 |
| 71 // Report that wait on the condition variable at address "cv" has succeeded |
| 72 // and the lock at address "lock" is held. |
| 73 #define ANNOTATE_CONDVAR_LOCK_WAIT(cv, lock) \ |
| 74 AnnotateCondVarWait(__FILE__, __LINE__, cv, lock) |
| 75 |
| 76 // Report that wait on the condition variable at "cv" has succeeded. Variant |
| 77 // w/o lock. |
| 78 #define ANNOTATE_CONDVAR_WAIT(cv) \ |
| 79 AnnotateCondVarWait(__FILE__, __LINE__, cv, NULL) |
| 80 |
| 81 // Report that we are about to signal on the condition variable at address |
| 82 // "cv". |
| 83 #define ANNOTATE_CONDVAR_SIGNAL(cv) \ |
| 84 AnnotateCondVarSignal(__FILE__, __LINE__, cv) |
| 85 |
| 86 // Report that we are about to signal_all on the condition variable at "cv". |
| 87 #define ANNOTATE_CONDVAR_SIGNAL_ALL(cv) \ |
| 88 AnnotateCondVarSignalAll(__FILE__, __LINE__, cv) |
| 89 |
| 90 // Annotations for user-defined synchronization mechanisms. |
| 91 #define ANNOTATE_HAPPENS_BEFORE(obj) ANNOTATE_CONDVAR_SIGNAL(obj) |
| 92 #define ANNOTATE_HAPPENS_AFTER(obj) ANNOTATE_CONDVAR_WAIT(obj) |
| 93 |
| 94 // Report that the bytes in the range [pointer, pointer+size) are about |
| 95 // to be published safely. The race checker will create a happens-before |
| 96 // arc from the call ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size) to |
| 97 // subsequent accesses to this memory. |
| 98 #define ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size) \ |
| 99 AnnotatePublishMemoryRange(__FILE__, __LINE__, pointer, size) |
| 100 |
| 101 // Instruct the tool to create a happens-before arc between mu->Unlock() and |
| 102 // mu->Lock(). This annotation may slow down the race detector; normally it |
| 103 // is used only when it would be difficult to annotate each of the mutex's |
| 104 // critical sections individually using the annotations above. |
| 105 #define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mu) \ |
| 106 AnnotateMutexIsUsedAsCondVar(__FILE__, __LINE__, mu) |
| 107 |
| 108 // ------------------------------------------------------------- |
| 109 // Annotations useful when defining memory allocators, or when memory that |
| 110 // was protected in one way starts to be protected in another. |
| 111 |
| 112 // Report that a new memory at "address" of size "size" has been allocated. |
| 113 // This might be used when the memory has been retrieved from a free list and |
| 114 // is about to be reused, or when a the locking discipline for a variable |
| 115 // changes. |
| 116 #define ANNOTATE_NEW_MEMORY(address, size) \ |
| 117 AnnotateNewMemory(__FILE__, __LINE__, address, size) |
| 118 |
| 119 // ------------------------------------------------------------- |
| 120 // Annotations useful when defining FIFO queues that transfer data between |
| 121 // threads. |
| 122 |
| 123 // Report that the producer-consumer queue (such as ProducerConsumerQueue) at |
| 124 // address "pcq" has been created. The ANNOTATE_PCQ_* annotations |
| 125 // should be used only for FIFO queues. For non-FIFO queues use |
| 126 // ANNOTATE_HAPPENS_BEFORE (for put) and ANNOTATE_HAPPENS_AFTER (for get). |
| 127 #define ANNOTATE_PCQ_CREATE(pcq) \ |
| 128 AnnotatePCQCreate(__FILE__, __LINE__, pcq) |
| 129 |
| 130 // Report that the queue at address "pcq" is about to be destroyed. |
| 131 #define ANNOTATE_PCQ_DESTROY(pcq) \ |
| 132 AnnotatePCQDestroy(__FILE__, __LINE__, pcq) |
| 133 |
| 134 // Report that we are about to put an element into a FIFO queue at address |
| 135 // "pcq". |
| 136 #define ANNOTATE_PCQ_PUT(pcq) \ |
| 137 AnnotatePCQPut(__FILE__, __LINE__, pcq) |
| 138 |
| 139 // Report that we've just got an element from a FIFO queue at address "pcq". |
| 140 #define ANNOTATE_PCQ_GET(pcq) \ |
| 141 AnnotatePCQGet(__FILE__, __LINE__, pcq) |
| 142 |
| 143 // ------------------------------------------------------------- |
| 144 // Annotations that suppress errors. It is usually better to express the |
| 145 // program's synchronization using the other annotations, but these can |
| 146 // be used when all else fails. |
| 147 |
| 148 // Report that we may have a benign race on at "address". |
| 149 // Insert at the point where "address" has been allocated, preferably close |
| 150 // to the point where the race happens. |
| 151 // See also ANNOTATE_BENIGN_RACE_STATIC. |
| 152 #define ANNOTATE_BENIGN_RACE(address, description) \ |
| 153 AnnotateBenignRace(__FILE__, __LINE__, address, description) |
| 154 |
| 155 // Request the analysis tool to ignore all reads in the current thread |
| 156 // until ANNOTATE_IGNORE_READS_END is called. |
| 157 // Useful to ignore intentional racey reads, while still checking |
| 158 // other reads and all writes. |
| 159 // See also ANNOTATE_UNPROTECTED_READ. |
| 160 #define ANNOTATE_IGNORE_READS_BEGIN() \ |
| 161 AnnotateIgnoreReadsBegin(__FILE__, __LINE__) |
| 162 |
| 163 // Stop ignoring reads. |
| 164 #define ANNOTATE_IGNORE_READS_END() \ |
| 165 AnnotateIgnoreReadsEnd(__FILE__, __LINE__) |
| 166 |
| 167 // Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes. |
| 168 #define ANNOTATE_IGNORE_WRITES_BEGIN() \ |
| 169 AnnotateIgnoreWritesBegin(__FILE__, __LINE__) |
| 170 |
| 171 // Stop ignoring writes. |
| 172 #define ANNOTATE_IGNORE_WRITES_END() \ |
| 173 AnnotateIgnoreWritesEnd(__FILE__, __LINE__) |
| 174 |
| 175 // Start ignoring all memory accesses (reads and writes). |
| 176 #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \ |
| 177 do {\ |
| 178 ANNOTATE_IGNORE_READS_BEGIN();\ |
| 179 ANNOTATE_IGNORE_WRITES_BEGIN();\ |
| 180 }while(0)\ |
| 181 |
| 182 // Stop ignoring all memory accesses. |
| 183 #define ANNOTATE_IGNORE_READS_AND_WRITES_END() \ |
| 184 do {\ |
| 185 ANNOTATE_IGNORE_WRITES_END();\ |
| 186 ANNOTATE_IGNORE_READS_END();\ |
| 187 }while(0)\ |
| 188 |
| 189 // ------------------------------------------------------------- |
| 190 // Annotations useful for debugging. |
| 191 |
| 192 // Request to trace every access to "address". |
| 193 #define ANNOTATE_TRACE_MEMORY(address) \ |
| 194 AnnotateTraceMemory(__FILE__, __LINE__, address) |
| 195 |
| 196 // Report the current thread name to a race detector. |
| 197 #define ANNOTATE_THREAD_NAME(name) \ |
| 198 AnnotateThreadName(__FILE__, __LINE__, name) |
| 199 |
| 200 // ------------------------------------------------------------- |
| 201 // Annotations useful when implementing locks. They are not |
| 202 // normally needed by modules that merely use locks. |
| 203 // The "lock" argument is a pointer to the lock object. |
| 204 |
| 205 // Report that a lock has been created at address "lock". |
| 206 #define ANNOTATE_RWLOCK_CREATE(lock) \ |
| 207 AnnotateRWLockCreate(__FILE__, __LINE__, lock) |
| 208 |
| 209 // Report that the lock at address "lock" is about to be destroyed. |
| 210 #define ANNOTATE_RWLOCK_DESTROY(lock) \ |
| 211 AnnotateRWLockDestroy(__FILE__, __LINE__, lock) |
| 212 |
| 213 // Report that the lock at address "lock" has been acquired. |
| 214 // is_w=1 for writer lock, is_w=0 for reader lock. |
| 215 #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \ |
| 216 AnnotateRWLockAcquired(__FILE__, __LINE__, lock, is_w) |
| 217 |
| 218 // Report that the lock at address "lock" is about to be released. |
| 219 #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \ |
| 220 AnnotateRWLockReleased(__FILE__, __LINE__, lock, is_w) |
| 221 |
| 222 // ------------------------------------------------------------- |
| 223 // Annotations useful for testing race detectors. |
| 224 |
| 225 // Report that we expect a race on the variable at "address". |
| 226 // Use only in unit tests for a race detector. |
| 227 #define ANNOTATE_EXPECT_RACE(address, description) \ |
| 228 AnnotateExpectRace(__FILE__, __LINE__, address, description) |
| 229 |
| 230 // A no-op. Insert where you like to test the interceptors. |
| 231 #define ANNOTATE_NO_OP(arg) \ |
| 232 AnnotateNoOp(__FILE__, __LINE__, arg) |
| 233 |
| 234 // Use the macros above rather than using these functions directly. |
| 235 extern "C" void AnnotateRWLockCreate(const char *file, int line, |
| 236 const volatile void *lock); |
| 237 extern "C" void AnnotateRWLockDestroy(const char *file, int line, |
| 238 const volatile void *lock); |
| 239 extern "C" void AnnotateRWLockAcquired(const char *file, int line, |
| 240 const volatile void *lock, long is_w); |
| 241 extern "C" void AnnotateRWLockReleased(const char *file, int line, |
| 242 const volatile void *lock, long is_w); |
| 243 extern "C" void AnnotateCondVarWait(const char *file, int line, |
| 244 const volatile void *cv, |
| 245 const volatile void *lock); |
| 246 extern "C" void AnnotateCondVarSignal(const char *file, int line, |
| 247 const volatile void *cv); |
| 248 extern "C" void AnnotateCondVarSignalAll(const char *file, int line, |
| 249 const volatile void *cv); |
| 250 extern "C" void AnnotatePublishMemoryRange(const char *file, int line, |
| 251 const volatile void *address, |
| 252 long size); |
| 253 extern "C" void AnnotatePCQCreate(const char *file, int line, |
| 254 const volatile void *pcq); |
| 255 extern "C" void AnnotatePCQDestroy(const char *file, int line, |
| 256 const volatile void *pcq); |
| 257 extern "C" void AnnotatePCQPut(const char *file, int line, |
| 258 const volatile void *pcq); |
| 259 extern "C" void AnnotatePCQGet(const char *file, int line, |
| 260 const volatile void *pcq); |
| 261 extern "C" void AnnotateNewMemory(const char *file, int line, |
| 262 const volatile void *address, |
| 263 long size); |
| 264 extern "C" void AnnotateExpectRace(const char *file, int line, |
| 265 const volatile void *address, |
| 266 const char *description); |
| 267 extern "C" void AnnotateBenignRace(const char *file, int line, |
| 268 const volatile void *address, |
| 269 const char *description); |
| 270 extern "C" void AnnotateMutexIsUsedAsCondVar(const char *file, int line, |
| 271 const volatile void *mu); |
| 272 extern "C" void AnnotateTraceMemory(const char *file, int line, |
| 273 const volatile void *arg); |
| 274 extern "C" void AnnotateThreadName(const char *file, int line, |
| 275 const char *name); |
| 276 extern "C" void AnnotateIgnoreReadsBegin(const char *file, int line); |
| 277 extern "C" void AnnotateIgnoreReadsEnd(const char *file, int line); |
| 278 extern "C" void AnnotateIgnoreWritesBegin(const char *file, int line); |
| 279 extern "C" void AnnotateIgnoreWritesEnd(const char *file, int line); |
| 280 extern "C" void AnnotateNoOp(const char *file, int line, |
| 281 const volatile void *arg); |
| 282 |
| 283 // ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads. |
| 284 // |
| 285 // Instead of doing |
| 286 // ANNOTATE_IGNORE_READS_BEGIN(); |
| 287 // ... = x; |
| 288 // ANNOTATE_IGNORE_READS_END(); |
| 289 // one can use |
| 290 // ... = ANNOTATE_UNPROTECTED_READ(x); |
| 291 template <class T> |
| 292 inline T ANNOTATE_UNPROTECTED_READ(const volatile T &x) { |
| 293 ANNOTATE_IGNORE_READS_BEGIN(); |
| 294 T res = x; |
| 295 ANNOTATE_IGNORE_READS_END(); |
| 296 return res; |
| 297 } |
| 298 |
| 299 // Apply ANNOTATE_BENIGN_RACE to a static variable. |
| 300 #define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \ |
| 301 namespace { \ |
| 302 class static_var ## _annotator { \ |
| 303 public: \ |
| 304 static_var ## _annotator() { \ |
| 305 ANNOTATE_BENIGN_RACE(&static_var, \ |
| 306 # static_var ": " description); \ |
| 307 } \ |
| 308 }; \ |
| 309 static static_var ## _annotator the ## static_var ## _annotator;\ |
| 310 } |
| 311 |
| 312 #else // NDEBUG is defined |
| 313 // Release build, empty macros. |
| 314 |
| 315 #define ANNOTATE_RWLOCK_CREATE(lock) // empty |
| 316 #define ANNOTATE_RWLOCK_DESTROY(lock) // empty |
| 317 #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) // empty |
| 318 #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) // empty |
| 319 #define ANNOTATE_CONDVAR_LOCK_WAIT(cv, lock) // empty |
| 320 #define ANNOTATE_CONDVAR_WAIT(cv) // empty |
| 321 #define ANNOTATE_CONDVAR_SIGNAL(cv) // empty |
| 322 #define ANNOTATE_CONDVAR_SIGNAL_ALL(cv) // empty |
| 323 #define ANNOTATE_HAPPENS_BEFORE(obj) // empty |
| 324 #define ANNOTATE_HAPPENS_AFTER(obj) // empty |
| 325 #define ANNOTATE_PUBLISH_MEMORY_RANGE(address, size) // empty |
| 326 #define ANNOTATE_PUBLISH_OBJECT(address) // empty |
| 327 #define ANNOTATE_PCQ_CREATE(pcq) // empty |
| 328 #define ANNOTATE_PCQ_DESTROY(pcq) // empty |
| 329 #define ANNOTATE_PCQ_PUT(pcq) // empty |
| 330 #define ANNOTATE_PCQ_GET(pcq) // empty |
| 331 #define ANNOTATE_NEW_MEMORY(address, size) // empty |
| 332 #define ANNOTATE_EXPECT_RACE(address, description) // empty |
| 333 #define ANNOTATE_BENIGN_RACE(address, description) // empty |
| 334 #define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mu) // empty |
| 335 #define ANNOTATE_TRACE_MEMORY(arg) // empty |
| 336 #define ANNOTATE_THREAD_NAME(name) // empty |
| 337 #define ANNOTATE_IGNORE_READS_BEGIN() // empty |
| 338 #define ANNOTATE_IGNORE_READS_END() // empty |
| 339 #define ANNOTATE_IGNORE_WRITES_BEGIN() // empty |
| 340 #define ANNOTATE_IGNORE_WRITES_END() // empty |
| 341 #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() // empty |
| 342 #define ANNOTATE_IGNORE_READS_AND_WRITES_END() // empty |
| 343 #define ANNOTATE_NO_OP(arg) // empty |
| 344 #define ANNOTATE_UNPROTECTED_READ(x) (x) |
| 345 #define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) // empty |
| 346 |
| 347 #endif // NDEBUG |
| 348 |
| 349 // Return non-zero value if running under valgrind. |
| 350 extern "C" int RunningOnValgrind(); |
| 351 |
| 352 #endif // BASE_DYNAMIC_ANNOTATIONS_H_ |
OLD | NEW |