1 /* 2 ---------------------------------------------------------------- 3 4 Notice that the following BSD-style license applies to this one 5 file (drd.h) only. The rest of Valgrind is licensed under the 6 terms of the GNU General Public License, version 2, unless 7 otherwise indicated. See the COPYING file in the source 8 distribution for details. 9 10 ---------------------------------------------------------------- 11 12 This file is part of DRD, a Valgrind tool for verification of 13 multithreaded programs. 14 15 Copyright (C) 2006-2012 Bart Van Assche <bvanassche (at) acm.org>. 16 All rights reserved. 17 18 Redistribution and use in source and binary forms, with or without 19 modification, are permitted provided that the following conditions 20 are met: 21 22 1. Redistributions of source code must retain the above copyright 23 notice, this list of conditions and the following disclaimer. 24 25 2. The origin of this software must not be misrepresented; you must 26 not claim that you wrote the original software. If you use this 27 software in a product, an acknowledgment in the product 28 documentation would be appreciated but is not required. 29 30 3. Altered source versions must be plainly marked as such, and must 31 not be misrepresented as being the original software. 32 33 4. The name of the author may not be used to endorse or promote 34 products derived from this software without specific prior written 35 permission. 36 37 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 38 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 39 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 40 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 41 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 42 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 43 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 44 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 45 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 46 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 47 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 48 49 ---------------------------------------------------------------- 50 51 Notice that the above BSD-style license applies to this one file 52 (drd.h) only. The entire rest of Valgrind is licensed under 53 the terms of the GNU General Public License, version 2. See the 54 COPYING file in the source distribution for details. 55 56 ---------------------------------------------------------------- 57 */ 58 59 #ifndef __VALGRIND_DRD_H 60 #define __VALGRIND_DRD_H 61 62 63 #include "valgrind.h" 64 65 66 /** Obtain the thread ID assigned by Valgrind's core. */ 67 #define DRD_GET_VALGRIND_THREADID \ 68 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \ 69 VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID, \ 70 0, 0, 0, 0, 0) 71 72 /** Obtain the thread ID assigned by DRD. */ 73 #define DRD_GET_DRD_THREADID \ 74 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \ 75 VG_USERREQ__DRD_GET_DRD_THREAD_ID, \ 76 0, 0, 0, 0, 0) 77 78 79 /** Tell DRD not to complain about data races for the specified variable. */ 80 #define DRD_IGNORE_VAR(x) ANNOTATE_BENIGN_RACE_SIZED(&(x), sizeof(x), "") 81 82 /** Tell DRD to no longer ignore data races for the specified variable. */ 83 #define DRD_STOP_IGNORING_VAR(x) \ 84 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_FINISH_SUPPRESSION, \ 85 &(x), sizeof(x), 0, 0, 0) 86 87 /** 88 * Tell DRD to trace all memory accesses for the specified variable 89 * until the memory that was allocated for the variable is freed. 90 */ 91 #define DRD_TRACE_VAR(x) \ 92 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_START_TRACE_ADDR, \ 93 &(x), sizeof(x), 0, 0, 0) 94 95 /** 96 * Tell DRD to stop tracing memory accesses for the specified variable. 97 */ 98 #define DRD_STOP_TRACING_VAR(x) \ 99 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_STOP_TRACE_ADDR, \ 100 &(x), sizeof(x), 0, 0, 0) 101 102 /** 103 * @defgroup RaceDetectionAnnotations Data race detection annotations. 104 * 105 * @see See also the source file <a href="http://code.google.com/p/data-race-test/source/browse/trunk/dynamic_annotations/dynamic_annotations.h</a> 106 107 * in the ThreadSanitizer project. 108 */ 109 /*@{*/ 110 111 #ifndef __HELGRIND_H 112 113 /** 114 * Tell DRD to insert a happens-before mark. addr is the address of an object 115 * that is not a pthread synchronization object. 116 */ 117 #define ANNOTATE_HAPPENS_BEFORE(addr) \ 118 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_HAPPENS_BEFORE, \ 119 addr, 0, 0, 0, 0) 120 121 /** 122 * Tell DRD that the memory accesses executed after this annotation will 123 * happen after all memory accesses performed before all preceding 124 * ANNOTATE_HAPPENS_BEFORE(addr). addr is the address of an object that is not 125 * a pthread synchronization object. Inserting a happens-after annotation 126 * before any other thread has passed by a happens-before annotation for the 127 * same address is an error. 128 */ 129 #define ANNOTATE_HAPPENS_AFTER(addr) \ 130 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_HAPPENS_AFTER, \ 131 addr, 0, 0, 0, 0) 132 133 #else /* __HELGRIND_H */ 134 135 #undef ANNOTATE_CONDVAR_LOCK_WAIT 136 #undef ANNOTATE_CONDVAR_WAIT 137 #undef ANNOTATE_CONDVAR_SIGNAL 138 #undef ANNOTATE_CONDVAR_SIGNAL_ALL 139 #undef ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX 140 #undef ANNOTATE_PUBLISH_MEMORY_RANGE 141 #undef ANNOTATE_BARRIER_INIT 142 #undef ANNOTATE_BARRIER_WAIT_BEFORE 143 #undef ANNOTATE_BARRIER_WAIT_AFTER 144 #undef ANNOTATE_BARRIER_DESTROY 145 #undef ANNOTATE_PCQ_CREATE 146 #undef ANNOTATE_PCQ_DESTROY 147 #undef ANNOTATE_PCQ_PUT 148 #undef ANNOTATE_PCQ_GET 149 #undef ANNOTATE_BENIGN_RACE 150 #undef ANNOTATE_BENIGN_RACE_SIZED 151 #undef ANNOTATE_IGNORE_READS_BEGIN 152 #undef ANNOTATE_IGNORE_READS_END 153 #undef ANNOTATE_IGNORE_WRITES_BEGIN 154 #undef ANNOTATE_IGNORE_WRITES_END 155 #undef ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN 156 #undef ANNOTATE_IGNORE_READS_AND_WRITES_END 157 #undef ANNOTATE_NEW_MEMORY 158 #undef ANNOTATE_TRACE_MEMORY 159 #undef ANNOTATE_THREAD_NAME 160 161 #endif /* __HELGRIND_H */ 162 163 /** 164 * Tell DRD that waiting on the condition variable at address cv has succeeded 165 * and a lock on the mutex at address mtx is now held. Since DRD always inserts 166 * a happens before relation between the pthread_cond_signal() or 167 * pthread_cond_broadcast() call that wakes up a pthread_cond_wait() or 168 * pthread_cond_timedwait() call and the woken up thread, this macro has been 169 * defined such that it has no effect. 170 */ 171 #define ANNOTATE_CONDVAR_LOCK_WAIT(cv, mtx) do { } while(0) 172 173 /** 174 * Tell DRD that the condition variable at address cv is about to be signaled. 175 */ 176 #define ANNOTATE_CONDVAR_SIGNAL(cv) do { } while(0) 177 178 /** 179 * Tell DRD that the condition variable at address cv is about to be signaled. 180 */ 181 #define ANNOTATE_CONDVAR_SIGNAL_ALL(cv) do { } while(0) 182 183 /** 184 * Tell DRD that waiting on condition variable at address cv succeeded and that 185 * the memory operations performed after this annotation should be considered 186 * to happen after the matching ANNOTATE_CONDVAR_SIGNAL(cv). Since this is the 187 * default behavior of DRD, this macro and the macro above have been defined 188 * such that they have no effect. 189 */ 190 #define ANNOTATE_CONDVAR_WAIT(cv) do { } while(0) 191 192 /** 193 * Tell DRD to consider the memory operations that happened before a mutex 194 * unlock event and after the subsequent mutex lock event on the same mutex as 195 * ordered. This is how DRD always behaves, so this macro has been defined 196 * such that it has no effect. 197 */ 198 #define ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mtx) do { } while(0) 199 200 /** Deprecated -- don't use this annotation. */ 201 #define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mtx) do { } while(0) 202 203 /** 204 * Tell DRD to handle the specified memory range like a pure happens-before 205 * detector would do. Since this is how DRD always behaves, this annotation 206 * has been defined such that it has no effect. 207 */ 208 #define ANNOTATE_PUBLISH_MEMORY_RANGE(addr, size) do { } while(0) 209 210 /** Deprecated -- don't use this annotation. */ 211 #define ANNOTATE_UNPUBLISH_MEMORY_RANGE(addr, size) do { } while(0) 212 213 /** Deprecated -- don't use this annotation. */ 214 #define ANNOTATE_SWAP_MEMORY_RANGE(addr, size) do { } while(0) 215 216 #ifndef __HELGRIND_H 217 218 /** Tell DRD that a reader-writer lock object has been initialized. */ 219 #define ANNOTATE_RWLOCK_CREATE(rwlock) \ 220 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_RWLOCK_CREATE, \ 221 rwlock, 0, 0, 0, 0); 222 223 /** Tell DRD that a reader-writer lock object has been destroyed. */ 224 #define ANNOTATE_RWLOCK_DESTROY(rwlock) \ 225 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_RWLOCK_DESTROY, \ 226 rwlock, 0, 0, 0, 0); 227 228 /** 229 * Tell DRD that a reader-writer lock has been acquired. is_w == 1 means that 230 * a write lock has been obtained, is_w == 0 means that a read lock has been 231 * obtained. 232 */ 233 #define ANNOTATE_RWLOCK_ACQUIRED(rwlock, is_w) \ 234 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_RWLOCK_ACQUIRED, \ 235 rwlock, is_w, 0, 0, 0) 236 237 #endif /* __HELGRIND_H */ 238 239 /** 240 * Tell DRD that a reader lock has been acquired on a reader-writer 241 * synchronization object. 242 */ 243 #define ANNOTATE_READERLOCK_ACQUIRED(rwlock) ANNOTATE_RWLOCK_ACQUIRED(rwlock, 0) 244 245 /** 246 * Tell DRD that a writer lock has been acquired on a reader-writer 247 * synchronization object. 248 */ 249 #define ANNOTATE_WRITERLOCK_ACQUIRED(rwlock) ANNOTATE_RWLOCK_ACQUIRED(rwlock, 1) 250 251 #ifndef __HELGRIND_H 252 253 /** 254 * Tell DRD that a reader-writer lock is about to be released. is_w == 1 means 255 * that a write lock is about to be released, is_w == 0 means that a read lock 256 * is about to be released. 257 */ 258 #define ANNOTATE_RWLOCK_RELEASED(rwlock, is_w) \ 259 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_RWLOCK_RELEASED, \ 260 rwlock, is_w, 0, 0, 0); 261 262 #endif /* __HELGRIND_H */ 263 264 /** 265 * Tell DRD that a reader lock is about to be released. 266 */ 267 #define ANNOTATE_READERLOCK_RELEASED(rwlock) ANNOTATE_RWLOCK_RELEASED(rwlock, 0) 268 269 /** 270 * Tell DRD that a writer lock is about to be released. 271 */ 272 #define ANNOTATE_WRITERLOCK_RELEASED(rwlock) ANNOTATE_RWLOCK_RELEASED(rwlock, 1) 273 274 /* 275 * Report that a barrier has been initialized with a given barrier count. The 276 * third argument specifies whether or not reinitialization is allowed, that 277 * is, whether or not it is allowed to call barrier_init() several times 278 * without calling barrier_destroy(). 279 */ 280 #define ANNOTATE_BARRIER_INIT(barrier, count, reinitialization_allowed) \ 281 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATION_UNIMP, \ 282 "ANNOTATE_BARRIER_INIT", barrier, \ 283 count, reinitialization_allowed, 0) 284 285 /* Report that a barrier has been destroyed. */ 286 #define ANNOTATE_BARRIER_DESTROY(barrier) \ 287 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATION_UNIMP, \ 288 "ANNOTATE_BARRIER_DESTROY", \ 289 barrier, 0, 0, 0) 290 291 /* Report that the calling thread is about to start waiting for a barrier. */ 292 #define ANNOTATE_BARRIER_WAIT_BEFORE(barrier) \ 293 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATION_UNIMP, \ 294 "ANNOTATE_BARRIER_WAIT_BEFORE", \ 295 barrier, 0, 0, 0) 296 297 /* Report that the calling thread has just finished waiting for a barrier. */ 298 #define ANNOTATE_BARRIER_WAIT_AFTER(barrier) \ 299 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATION_UNIMP, \ 300 "ANNOTATE_BARRIER_WAIT_AFTER", \ 301 barrier, 0, 0, 0) 302 303 /** 304 * Tell DRD that a FIFO queue has been created. The abbreviation PCQ stands for 305 * <em>producer-consumer</em>. 306 */ 307 #define ANNOTATE_PCQ_CREATE(pcq) do { } while(0) 308 309 /** Tell DRD that a FIFO queue has been destroyed. */ 310 #define ANNOTATE_PCQ_DESTROY(pcq) do { } while(0) 311 312 /** 313 * Tell DRD that an element has been added to the FIFO queue at address pcq. 314 */ 315 #define ANNOTATE_PCQ_PUT(pcq) do { } while(0) 316 317 /** 318 * Tell DRD that an element has been removed from the FIFO queue at address pcq, 319 * and that DRD should insert a happens-before relationship between the memory 320 * accesses that occurred before the corresponding ANNOTATE_PCQ_PUT(pcq) 321 * annotation and the memory accesses after this annotation. Correspondence 322 * between PUT and GET annotations happens in FIFO order. Since locking 323 * of the queue is needed anyway to add elements to or to remove elements from 324 * the queue, for DRD all four FIFO annotations are defined as no-ops. 325 */ 326 #define ANNOTATE_PCQ_GET(pcq) do { } while(0) 327 328 /** 329 * Tell DRD that data races at the specified address are expected and must not 330 * be reported. 331 */ 332 #define ANNOTATE_BENIGN_RACE(addr, descr) \ 333 ANNOTATE_BENIGN_RACE_SIZED(addr, sizeof(*addr), descr) 334 335 /* Same as ANNOTATE_BENIGN_RACE(addr, descr), but applies to 336 the memory range [addr, addr + size). */ 337 #define ANNOTATE_BENIGN_RACE_SIZED(addr, size, descr) \ 338 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_START_SUPPRESSION, \ 339 addr, size, 0, 0, 0) 340 341 /** Tell DRD to ignore all reads performed by the current thread. */ 342 #define ANNOTATE_IGNORE_READS_BEGIN() \ 343 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_RECORD_LOADS, \ 344 0, 0, 0, 0, 0); 345 346 347 /** Tell DRD to no longer ignore the reads performed by the current thread. */ 348 #define ANNOTATE_IGNORE_READS_END() \ 349 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_RECORD_LOADS, \ 350 1, 0, 0, 0, 0); 351 352 /** Tell DRD to ignore all writes performed by the current thread. */ 353 #define ANNOTATE_IGNORE_WRITES_BEGIN() \ 354 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_RECORD_STORES, \ 355 0, 0, 0, 0, 0) 356 357 /** Tell DRD to no longer ignore the writes performed by the current thread. */ 358 #define ANNOTATE_IGNORE_WRITES_END() \ 359 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_RECORD_STORES, \ 360 1, 0, 0, 0, 0) 361 362 /** Tell DRD to ignore all memory accesses performed by the current thread. */ 363 #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \ 364 do { ANNOTATE_IGNORE_READS_BEGIN(); ANNOTATE_IGNORE_WRITES_BEGIN(); } while(0) 365 366 /** 367 * Tell DRD to no longer ignore the memory accesses performed by the current 368 * thread. 369 */ 370 #define ANNOTATE_IGNORE_READS_AND_WRITES_END() \ 371 do { ANNOTATE_IGNORE_READS_END(); ANNOTATE_IGNORE_WRITES_END(); } while(0) 372 373 /** 374 * Tell DRD that size bytes starting at addr has been allocated by a custom 375 * memory allocator. 376 */ 377 #define ANNOTATE_NEW_MEMORY(addr, size) \ 378 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_CLEAN_MEMORY, \ 379 addr, size, 0, 0, 0) 380 381 /** Ask DRD to report every access to the specified address. */ 382 #define ANNOTATE_TRACE_MEMORY(addr) DRD_TRACE_VAR(*(char*)(addr)) 383 384 /** 385 * Tell DRD to assign the specified name to the current thread. This name will 386 * be used in error messages printed by DRD. 387 */ 388 #define ANNOTATE_THREAD_NAME(name) \ 389 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_SET_THREAD_NAME, \ 390 name, 0, 0, 0, 0) 391 392 /*@}*/ 393 394 395 /* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! 396 This enum comprises an ABI exported by Valgrind to programs 397 which use client requests. DO NOT CHANGE THE ORDER OF THESE 398 ENTRIES, NOR DELETE ANY -- add new ones at the end. 399 */ 400 enum { 401 /* Ask the DRD tool to discard all information about memory accesses */ 402 /* and client objects for the specified range. This client request is */ 403 /* binary compatible with the similarly named Helgrind client request. */ 404 VG_USERREQ__DRD_CLEAN_MEMORY = VG_USERREQ_TOOL_BASE('H','G'), 405 /* args: Addr, SizeT. */ 406 407 /* Ask the DRD tool the thread ID assigned by Valgrind. */ 408 VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID = VG_USERREQ_TOOL_BASE('D','R'), 409 /* args: none. */ 410 /* Ask the DRD tool the thread ID assigned by DRD. */ 411 VG_USERREQ__DRD_GET_DRD_THREAD_ID, 412 /* args: none. */ 413 414 /* To tell the DRD tool to suppress data race detection on the */ 415 /* specified address range. */ 416 VG_USERREQ__DRD_START_SUPPRESSION, 417 /* args: start address, size in bytes */ 418 /* To tell the DRD tool no longer to suppress data race detection on */ 419 /* the specified address range. */ 420 VG_USERREQ__DRD_FINISH_SUPPRESSION, 421 /* args: start address, size in bytes */ 422 423 /* To ask the DRD tool to trace all accesses to the specified range. */ 424 VG_USERREQ__DRD_START_TRACE_ADDR, 425 /* args: Addr, SizeT. */ 426 /* To ask the DRD tool to stop tracing accesses to the specified range. */ 427 VG_USERREQ__DRD_STOP_TRACE_ADDR, 428 /* args: Addr, SizeT. */ 429 430 /* Tell DRD whether or not to record memory loads in the calling thread. */ 431 VG_USERREQ__DRD_RECORD_LOADS, 432 /* args: Bool. */ 433 /* Tell DRD whether or not to record memory stores in the calling thread. */ 434 VG_USERREQ__DRD_RECORD_STORES, 435 /* args: Bool. */ 436 437 /* Set the name of the thread that performs this client request. */ 438 VG_USERREQ__DRD_SET_THREAD_NAME, 439 /* args: null-terminated character string. */ 440 441 /* Tell DRD that a DRD annotation has not yet been implemented. */ 442 VG_USERREQ__DRD_ANNOTATION_UNIMP, 443 /* args: Char*. */ 444 445 /* Tell DRD that a user-defined reader-writer synchronization object 446 * has been created. */ 447 VG_USERREQ__DRD_ANNOTATE_RWLOCK_CREATE 448 = VG_USERREQ_TOOL_BASE('H','G') + 256 + 14, 449 /* args: Addr. */ 450 /* Tell DRD that a user-defined reader-writer synchronization object 451 * is about to be destroyed. */ 452 VG_USERREQ__DRD_ANNOTATE_RWLOCK_DESTROY 453 = VG_USERREQ_TOOL_BASE('H','G') + 256 + 15, 454 /* args: Addr. */ 455 /* Tell DRD that a lock on a user-defined reader-writer synchronization 456 * object has been acquired. */ 457 VG_USERREQ__DRD_ANNOTATE_RWLOCK_ACQUIRED 458 = VG_USERREQ_TOOL_BASE('H','G') + 256 + 17, 459 /* args: Addr, Int is_rw. */ 460 /* Tell DRD that a lock on a user-defined reader-writer synchronization 461 * object is about to be released. */ 462 VG_USERREQ__DRD_ANNOTATE_RWLOCK_RELEASED 463 = VG_USERREQ_TOOL_BASE('H','G') + 256 + 18, 464 /* args: Addr, Int is_rw. */ 465 466 /* Tell DRD that a Helgrind annotation has not yet been implemented. */ 467 VG_USERREQ__HELGRIND_ANNOTATION_UNIMP 468 = VG_USERREQ_TOOL_BASE('H','G') + 256 + 32, 469 /* args: Char*. */ 470 471 /* Tell DRD to insert a happens-before annotation. */ 472 VG_USERREQ__DRD_ANNOTATE_HAPPENS_BEFORE 473 = VG_USERREQ_TOOL_BASE('H','G') + 256 + 33, 474 /* args: Addr. */ 475 /* Tell DRD to insert a happens-after annotation. */ 476 VG_USERREQ__DRD_ANNOTATE_HAPPENS_AFTER 477 = VG_USERREQ_TOOL_BASE('H','G') + 256 + 34, 478 /* args: Addr. */ 479 480 }; 481 482 483 /** 484 * @addtogroup RaceDetectionAnnotations 485 */ 486 /*@{*/ 487 488 #ifdef __cplusplus 489 /* ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racy reads. 490 491 Instead of doing 492 ANNOTATE_IGNORE_READS_BEGIN(); 493 ... = x; 494 ANNOTATE_IGNORE_READS_END(); 495 one can use 496 ... = ANNOTATE_UNPROTECTED_READ(x); */ 497 template <typename T> 498 inline T ANNOTATE_UNPROTECTED_READ(const volatile T& x) { 499 ANNOTATE_IGNORE_READS_BEGIN(); 500 const T result = x; 501 ANNOTATE_IGNORE_READS_END(); 502 return result; 503 } 504 /* Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable. */ 505 #define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \ 506 namespace { \ 507 static class static_var##_annotator \ 508 { \ 509 public: \ 510 static_var##_annotator() \ 511 { \ 512 ANNOTATE_BENIGN_RACE_SIZED(&static_var, sizeof(static_var), \ 513 #static_var ": " description); \ 514 } \ 515 } the_##static_var##_annotator; \ 516 } 517 #endif 518 519 /*@}*/ 520 521 #endif /* __VALGRIND_DRD_H */ 522