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-2013 Bart Van Assche <bvanassche@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/** Tell DRD that a semaphore object is going to be initialized. */
275#define ANNOTATE_SEM_INIT_PRE(sem, value)                                 \
276   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_SEM_INIT_PRE, \
277                                   sem, value, 0, 0, 0);
278
279/** Tell DRD that a semaphore object has been destroyed. */
280#define ANNOTATE_SEM_DESTROY_POST(sem)                                        \
281   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_SEM_DESTROY_POST, \
282                                   sem, 0, 0, 0, 0);
283
284/** Tell DRD that a semaphore is going to be acquired. */
285#define ANNOTATE_SEM_WAIT_PRE(sem)                                        \
286   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_SEM_WAIT_PRE, \
287                                   sem, 0, 0, 0, 0)
288
289/** Tell DRD that a semaphore has been acquired. */
290#define ANNOTATE_SEM_WAIT_POST(sem)                                        \
291   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_SEM_WAIT_POST, \
292                                   sem, 0, 0, 0, 0)
293
294/** Tell DRD that a semaphore is going to be released. */
295#define ANNOTATE_SEM_POST_PRE(sem)                                        \
296   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_SEM_POST_PRE, \
297                                   sem, 0, 0, 0, 0)
298
299/*
300 * Report that a barrier has been initialized with a given barrier count.  The
301 * third argument specifies whether or not reinitialization is allowed, that
302 * is, whether or not it is allowed to call barrier_init() several times
303 * without calling barrier_destroy().
304 */
305#define ANNOTATE_BARRIER_INIT(barrier, count, reinitialization_allowed) \
306   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATION_UNIMP,    \
307                                   "ANNOTATE_BARRIER_INIT", barrier,    \
308                                   count, reinitialization_allowed, 0)
309
310/* Report that a barrier has been destroyed. */
311#define ANNOTATE_BARRIER_DESTROY(barrier)                               \
312   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATION_UNIMP,    \
313                                   "ANNOTATE_BARRIER_DESTROY",          \
314                                   barrier, 0, 0, 0)
315
316/* Report that the calling thread is about to start waiting for a barrier. */
317#define ANNOTATE_BARRIER_WAIT_BEFORE(barrier)                           \
318   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATION_UNIMP,    \
319                                   "ANNOTATE_BARRIER_WAIT_BEFORE",      \
320                                   barrier, 0, 0, 0)
321
322/* Report that the calling thread has just finished waiting for a barrier. */
323#define ANNOTATE_BARRIER_WAIT_AFTER(barrier)                            \
324   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATION_UNIMP,    \
325                                   "ANNOTATE_BARRIER_WAIT_AFTER",       \
326                                   barrier, 0, 0, 0)
327
328/**
329 * Tell DRD that a FIFO queue has been created. The abbreviation PCQ stands for
330 * <em>producer-consumer</em>.
331 */
332#define ANNOTATE_PCQ_CREATE(pcq) do { } while(0)
333
334/** Tell DRD that a FIFO queue has been destroyed. */
335#define ANNOTATE_PCQ_DESTROY(pcq) do { } while(0)
336
337/**
338 * Tell DRD that an element has been added to the FIFO queue at address pcq.
339 */
340#define ANNOTATE_PCQ_PUT(pcq) do { } while(0)
341
342/**
343 * Tell DRD that an element has been removed from the FIFO queue at address pcq,
344 * and that DRD should insert a happens-before relationship between the memory
345 * accesses that occurred before the corresponding ANNOTATE_PCQ_PUT(pcq)
346 * annotation and the memory accesses after this annotation. Correspondence
347 * between PUT and GET annotations happens in FIFO order. Since locking
348 * of the queue is needed anyway to add elements to or to remove elements from
349 * the queue, for DRD all four FIFO annotations are defined as no-ops.
350 */
351#define ANNOTATE_PCQ_GET(pcq) do { } while(0)
352
353/**
354 * Tell DRD that data races at the specified address are expected and must not
355 * be reported.
356 */
357#define ANNOTATE_BENIGN_RACE(addr, descr) \
358   ANNOTATE_BENIGN_RACE_SIZED(addr, sizeof(*addr), descr)
359
360/* Same as ANNOTATE_BENIGN_RACE(addr, descr), but applies to
361   the memory range [addr, addr + size). */
362#define ANNOTATE_BENIGN_RACE_SIZED(addr, size, descr)                   \
363   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_START_SUPPRESSION,   \
364                                   addr, size, 0, 0, 0)
365
366/** Tell DRD to ignore all reads performed by the current thread. */
367#define ANNOTATE_IGNORE_READS_BEGIN()                                \
368   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_RECORD_LOADS,     \
369                                   0, 0, 0, 0, 0);
370
371
372/** Tell DRD to no longer ignore the reads performed by the current thread. */
373#define ANNOTATE_IGNORE_READS_END()                                  \
374   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_RECORD_LOADS,     \
375                                   1, 0, 0, 0, 0);
376
377/** Tell DRD to ignore all writes performed by the current thread. */
378#define ANNOTATE_IGNORE_WRITES_BEGIN()                                \
379   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_RECORD_STORES,     \
380                                   0, 0, 0, 0, 0)
381
382/** Tell DRD to no longer ignore the writes performed by the current thread. */
383#define ANNOTATE_IGNORE_WRITES_END()                                  \
384   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_RECORD_STORES,     \
385                                   1, 0, 0, 0, 0)
386
387/** Tell DRD to ignore all memory accesses performed by the current thread. */
388#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
389   do { ANNOTATE_IGNORE_READS_BEGIN(); ANNOTATE_IGNORE_WRITES_BEGIN(); } while(0)
390
391/**
392 * Tell DRD to no longer ignore the memory accesses performed by the current
393 * thread.
394 */
395#define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
396   do { ANNOTATE_IGNORE_READS_END(); ANNOTATE_IGNORE_WRITES_END(); } while(0)
397
398/**
399 * Tell DRD that size bytes starting at addr has been allocated by a custom
400 * memory allocator.
401 */
402#define ANNOTATE_NEW_MEMORY(addr, size)                           \
403   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_CLEAN_MEMORY,  \
404                                   addr, size, 0, 0, 0)
405
406/** Ask DRD to report every access to the specified address. */
407#define ANNOTATE_TRACE_MEMORY(addr) DRD_TRACE_VAR(*(char*)(addr))
408
409/**
410 * Tell DRD to assign the specified name to the current thread. This name will
411 * be used in error messages printed by DRD.
412 */
413#define ANNOTATE_THREAD_NAME(name)                                      \
414   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_SET_THREAD_NAME,     \
415                                   name, 0, 0, 0, 0)
416
417/*@}*/
418
419
420/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
421   This enum comprises an ABI exported by Valgrind to programs
422   which use client requests.  DO NOT CHANGE THE ORDER OF THESE
423   ENTRIES, NOR DELETE ANY -- add new ones at the end.
424*/
425enum {
426   /* Ask the DRD tool to discard all information about memory accesses   */
427   /* and client objects for the specified range. This client request is  */
428   /* binary compatible with the similarly named Helgrind client request. */
429   VG_USERREQ__DRD_CLEAN_MEMORY = VG_USERREQ_TOOL_BASE('H','G'),
430   /* args: Addr, SizeT. */
431
432   /* Ask the DRD tool the thread ID assigned by Valgrind. */
433   VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID = VG_USERREQ_TOOL_BASE('D','R'),
434   /* args: none. */
435   /* Ask the DRD tool the thread ID assigned by DRD. */
436   VG_USERREQ__DRD_GET_DRD_THREAD_ID,
437   /* args: none. */
438
439   /* To tell the DRD tool to suppress data race detection on the */
440   /* specified address range. */
441   VG_USERREQ__DRD_START_SUPPRESSION,
442   /* args: start address, size in bytes */
443   /* To tell the DRD tool no longer to suppress data race detection on */
444   /* the specified address range. */
445   VG_USERREQ__DRD_FINISH_SUPPRESSION,
446   /* args: start address, size in bytes */
447
448   /* To ask the DRD tool to trace all accesses to the specified range. */
449   VG_USERREQ__DRD_START_TRACE_ADDR,
450   /* args: Addr, SizeT. */
451   /* To ask the DRD tool to stop tracing accesses to the specified range. */
452   VG_USERREQ__DRD_STOP_TRACE_ADDR,
453   /* args: Addr, SizeT. */
454
455   /* Tell DRD whether or not to record memory loads in the calling thread. */
456   VG_USERREQ__DRD_RECORD_LOADS,
457   /* args: Bool. */
458   /* Tell DRD whether or not to record memory stores in the calling thread. */
459   VG_USERREQ__DRD_RECORD_STORES,
460   /* args: Bool. */
461
462   /* Set the name of the thread that performs this client request. */
463   VG_USERREQ__DRD_SET_THREAD_NAME,
464   /* args: null-terminated character string. */
465
466   /* Tell DRD that a DRD annotation has not yet been implemented. */
467   VG_USERREQ__DRD_ANNOTATION_UNIMP,
468   /* args: char*. */
469
470   /* Tell DRD that a user-defined semaphore synchronization object
471    * is about to be created. */
472   VG_USERREQ__DRD_ANNOTATE_SEM_INIT_PRE,
473   /* args: Addr, UInt value. */
474   /* Tell DRD that a user-defined semaphore synchronization object
475    * has been destroyed. */
476   VG_USERREQ__DRD_ANNOTATE_SEM_DESTROY_POST,
477   /* args: Addr. */
478   /* Tell DRD that a user-defined semaphore synchronization
479    * object is going to be acquired (semaphore wait). */
480   VG_USERREQ__DRD_ANNOTATE_SEM_WAIT_PRE,
481   /* args: Addr. */
482   /* Tell DRD that a user-defined semaphore synchronization
483    * object has been acquired (semaphore wait). */
484   VG_USERREQ__DRD_ANNOTATE_SEM_WAIT_POST,
485   /* args: Addr. */
486   /* Tell DRD that a user-defined semaphore synchronization
487    * object is about to be released (semaphore post). */
488   VG_USERREQ__DRD_ANNOTATE_SEM_POST_PRE,
489   /* args: Addr. */
490
491   /* Tell DRD that a user-defined reader-writer synchronization object
492    * has been created. */
493   VG_USERREQ__DRD_ANNOTATE_RWLOCK_CREATE
494      = VG_USERREQ_TOOL_BASE('H','G') + 256 + 14,
495   /* args: Addr. */
496   /* Tell DRD that a user-defined reader-writer synchronization object
497    * is about to be destroyed. */
498   VG_USERREQ__DRD_ANNOTATE_RWLOCK_DESTROY
499      = VG_USERREQ_TOOL_BASE('H','G') + 256 + 15,
500   /* args: Addr. */
501   /* Tell DRD that a lock on a user-defined reader-writer synchronization
502    * object has been acquired. */
503   VG_USERREQ__DRD_ANNOTATE_RWLOCK_ACQUIRED
504      = VG_USERREQ_TOOL_BASE('H','G') + 256 + 17,
505   /* args: Addr, Int is_rw. */
506   /* Tell DRD that a lock on a user-defined reader-writer synchronization
507    * object is about to be released. */
508   VG_USERREQ__DRD_ANNOTATE_RWLOCK_RELEASED
509      = VG_USERREQ_TOOL_BASE('H','G') + 256 + 18,
510   /* args: Addr, Int is_rw. */
511
512   /* Tell DRD that a Helgrind annotation has not yet been implemented. */
513   VG_USERREQ__HELGRIND_ANNOTATION_UNIMP
514      = VG_USERREQ_TOOL_BASE('H','G') + 256 + 32,
515   /* args: char*. */
516
517   /* Tell DRD to insert a happens-before annotation. */
518   VG_USERREQ__DRD_ANNOTATE_HAPPENS_BEFORE
519      = VG_USERREQ_TOOL_BASE('H','G') + 256 + 33,
520   /* args: Addr. */
521   /* Tell DRD to insert a happens-after annotation. */
522   VG_USERREQ__DRD_ANNOTATE_HAPPENS_AFTER
523      = VG_USERREQ_TOOL_BASE('H','G') + 256 + 34,
524   /* args: Addr. */
525
526};
527
528
529/**
530 * @addtogroup RaceDetectionAnnotations
531 */
532/*@{*/
533
534#ifdef __cplusplus
535/* ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racy reads.
536
537   Instead of doing
538   ANNOTATE_IGNORE_READS_BEGIN();
539   ... = x;
540   ANNOTATE_IGNORE_READS_END();
541   one can use
542   ... = ANNOTATE_UNPROTECTED_READ(x); */
543template <typename T>
544inline T ANNOTATE_UNPROTECTED_READ(const volatile T& x) {
545   ANNOTATE_IGNORE_READS_BEGIN();
546   const T result = x;
547   ANNOTATE_IGNORE_READS_END();
548   return result;
549}
550/* Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable. */
551#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description)		\
552   namespace {								\
553      static class static_var##_annotator				\
554      {									\
555      public:								\
556	 static_var##_annotator()					\
557	 {								\
558	    ANNOTATE_BENIGN_RACE_SIZED(&static_var, sizeof(static_var),	\
559				       #static_var ": " description);	\
560	 }								\
561      } the_##static_var##_annotator;					\
562   }
563#endif
564
565/*@}*/
566
567#endif /* __VALGRIND_DRD_H */
568