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