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