drd.h revision 82c54c4d81b24bdfd3837d69ccbb2a69f8780848
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/**
82 * Tell DRD to trace all memory accesses on the specified variable.
83 * until the memory that was allocated for the variable is freed.
84 */
85#define DRD_TRACE_VAR(x) DRDCL_(trace_range)(&(x), sizeof(x))
86
87/* !! APIWARNING !! APIWARNING !! APIWARNING !! APIWARNING !!
88   The semantics and the names of the macro's defined below are still
89   under discussion and subject to change without notice.
90*/
91
92/**
93 * Tell DRD to insert a mark. addr is the address of an object that is not a
94 * pthread synchronization object. Inserting two 'happens before' annotations
95 * while no thread has passed by a 'happens after' annotation is an error.
96 */
97#define ANNOTATE_HAPPENS_BEFORE(addr) DRDCL_(annotate_happens_before)(addr)
98
99/**
100 * Tell DRD that the memory accesses executed after this annotation will happen
101 * after the memory accesses performed before the most recent
102 * ANNOTATE_HAPPENS_BEFORE(addr). addr is the address of an object that is not
103 * a pthread synchronization object. Inserting a 'happens after' annotation
104 * before any other thread has passed by a 'happens before' annotation for the
105 * same address is an error.
106 */
107#define ANNOTATE_HAPPENS_AFTER(addr) DRDCL_(annotate_happens_after)(addr)
108
109/**
110 * Tell DRD that waiting on the condition variable at address cv has succeeded
111 * and a lock on the mutex at address mtx is now held. Since DRD always inserts
112 * a happens before relation between the pthread_cond_signal() or
113 * pthread_cond_broadcast() call that wakes up a pthread_cond_wait() or
114 * pthread_cond_timedwait() call and the woken up thread, this macro has been
115 * defined such that it has no effect.
116 */
117#define ANNOTATE_CONDVAR_LOCK_WAIT(cv, mtx) do { } while(0)
118
119/**
120 * Tell DRD that the condition variable at address cv is about to be signaled.
121 */
122#define ANNOTATE_CONDVAR_SIGNAL(cv) do { } while(0)
123
124/**
125 * Tell DRD that waiting on condition variable at address cv succeeded and that
126 * the memory operations performed after this annotation should be considered
127 * to happen after the matching ANNOTATE_CONDVAR_SIGNAL(cv). Since this is the
128 * default behavior of DRD, this macro and the macro above have been defined
129 * such that they have no effect.
130 */
131#define ANNOTATE_CONDVAR_WAIT(cv) do { } while(0)
132
133/**
134 * Tell DRD to consider the memory operations that happened before a mutex
135 * unlock event and after the subsequent mutex lock event on the same mutex as
136 * ordered. This is how DRD always behaves, so this macro has been defined
137 * such that it has no effect.
138 */
139#define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mtx) do { } while(0)
140
141/**
142 * Tell DRD to handle the specified memory range like a pure happens-before
143 * detector would do. Since this is how DRD always behaves, this annotation
144 * has been defined such that it has no effect.
145 */
146#define ANNOTATE_PUBLISH_MEMORY_RANGE(addr, size) do { } while(0)
147
148/**
149 * Tell DRD to undo the effect of ANNOTATE_PUBLISH_MEMORY_RANGE().
150 */
151#define ANNOTATE_UNPUBLISH_MEMORY_RANGE(addr, size) do { } while(0)
152
153/** Tell DRD that a reader-writer lock object has been initialized. */
154#define ANNOTATE_RWLOCK_CREATE(rwlock) \
155   DRDCL_(annotate_rwlock)(rwlock, 0, 0)
156
157/** Tell DRD that a reader-writer lock object has been destroyed. */
158#define ANNOTATE_RWLOCK_DESTROY(rwlock) \
159   DRDCL_(annotate_rwlock)(rwlock, 1, 0)
160
161/**
162 * Tell DRD that a reader-writer lock has been acquired. is_w == 1 means that
163 * a write lock has been obtained, is_w == 0 means that a read lock has been
164 * obtained.
165 */
166#define ANNOTATE_RWLOCK_ACQUIRED(rwlock, is_w) \
167   DRDCL_(annotate_rwlock)(rwlock, 2, is_w)
168
169/**
170 * Tell DRD that a reader-writer lock is about to be released. is_w == 1 means
171 * that a write lock is about to be released, is_w == 0 means that a read lock
172 * is about to be released.
173 */
174#define ANNOTATE_RWLOCK_RELEASED(rwlock, is_w) \
175   DRDCL_(annotate_rwlock)(rwlock, 3, is_w)
176
177/**
178 * Tell DRD that a FIFO queue has been created. The abbreviation PCQ stands for
179 * <em>producer-consumer</em>.
180 */
181#define ANNOTATE_PCQ_CREATE(pcq) do { } while(0)
182
183/** Tell DRD that a FIFO queue has been destroyed. */
184#define ANNOTATE_PCQ_DESTROY(pcq) do { } while(0)
185
186/**
187 * Tell DRD that an element has been added to the FIFO queue at address pcq.
188 */
189#define ANNOTATE_PCQ_PUT(pcq) do { } while(0)
190
191/**
192 * Tell DRD that an element has been removed from the FIFO queue at address pcq,
193 * and that DRD should insert a happens-before relationship between the memory
194 * accesses that occurred before the corresponding ANNOTATE_PCQ_PUT(pcq)
195 * annotation and the memory accesses after this annotation. Correspondence
196 * between PUT and GET annotations happens in FIFO order. Since locking
197 * of the queue is needed anyway to add elements to or to remove elements from
198 * the queue, for DRD all four FIFO annotations are defined as no-ops.
199 */
200#define ANNOTATE_PCQ_GET(pcq) do { } while(0)
201
202/**
203 * Tell DRD that data races in the specified address range are expected and
204 * must not be reported.
205 */
206#define ANNOTATE_BENIGN_RACE(addr, descr) DRDCL_(ignore_range)(addr, 4)
207
208/** Tell DRD to ignore all reads performed by the current thread. */
209#define ANNOTATE_IGNORE_READS_BEGIN() DRDCL_(set_record_loads)(0)
210
211/** Tell DRD to no longer ignore the reads performed by the current thread. */
212#define ANNOTATE_IGNORE_READS_END() DRDCL_(set_record_loads)(1)
213
214/** Tell DRD to ignore all writes performed by the current thread. */
215#define ANNOTATE_IGNORE_WRITES_BEGIN() DRDCL_(set_record_stores)(0)
216
217/** Tell DRD to no longer ignore the writes performed by the current thread. */
218#define ANNOTATE_IGNORE_WRITES_END() DRDCL_(set_record_stores)(1)
219
220/** Tell DRD to ignore all memory accesses performed by the current thread. */
221#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
222   do { DRDCL_(set_record_loads)(0); DRD_(set_record_stores)(0); } while(0)
223
224/**
225 * Tell DRD to no longer ignore the memory accesses performed by the current
226 * thread.
227 */
228#define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
229   do { DRDCL_(set_record_loads)(1); DRD_(set_record_stores)(1); } while(0)
230
231/**
232 * Tell DRD that size bytes starting at addr has been allocated by a custom
233 * memory allocator.
234 */
235#define ANNOTATE_NEW_MEMORY(addr, size) DRDCL_(clean_memory)(addr, size)
236
237/** Ask DRD to report every access to the specified address range. */
238#define ANNOTATE_TRACE_MEMORY(addr) DRDCL_(trace_range)(addr, 1)
239
240/**
241 * Tell DRD to assign the specified name to the current thread. This name will
242 * be used in error messages printed by DRD.
243 */
244#define ANNOTATE_THREAD_NAME(name) DRDCL_(set_thread_name)(name)
245
246/* !! APIWARNING !! APIWARNING !! APIWARNING !! APIWARNING !!
247   The semantics and the names of the macro's defined above are still
248   under discussion and subject to change without notice.
249*/
250
251
252/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
253   This enum comprises an ABI exported by Valgrind to programs
254   which use client requests.  DO NOT CHANGE THE ORDER OF THESE
255   ENTRIES, NOR DELETE ANY -- add new ones at the end.
256*/
257enum {
258   /* Ask the DRD tool to discard all information about memory accesses   */
259   /* and client objects for the specified range. This client request is  */
260   /* binary compatible with the similarly named Helgrind client request. */
261   VG_USERREQ__DRD_CLEAN_MEMORY = VG_USERREQ_TOOL_BASE('H','G'),
262   /* args: Addr, SizeT. */
263
264   /* Ask the DRD tool the thread ID assigned by Valgrind. */
265   VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID = VG_USERREQ_TOOL_BASE('D','R'),
266   /* args: none. */
267   /* Ask the DRD tool the thread ID assigned by DRD. */
268   VG_USERREQ__DRD_GET_DRD_THREAD_ID,
269   /* args: none. */
270
271   /* To tell the DRD tool to suppress data race detection on the */
272   /* specified address range. */
273   VG_USERREQ__DRD_START_SUPPRESSION,
274   /* args: start address, size in bytes */
275   /* To tell the DRD tool no longer to suppress data race detection on */
276   /* the specified address range. */
277   VG_USERREQ__DRD_FINISH_SUPPRESSION,
278   /* args: start address, size in bytes */
279
280   /* To ask the DRD tool to trace all accesses to the specified range. */
281   VG_USERREQ__DRD_START_TRACE_ADDR,
282   /* args: Addr, SizeT. */
283   /* To ask the DRD tool to stop tracing accesses to the specified range. */
284   VG_USERREQ__DRD_STOP_TRACE_ADDR,
285   /* args: Addr, SizeT. */
286
287   /* Tell DRD whether or not to record memory loads in the calling thread. */
288   VG_USERREQ__DRD_RECORD_LOADS,
289   /* args: Bool. */
290   /* Tell DRD whether or not to record memory stores in the calling thread. */
291   VG_USERREQ__DRD_RECORD_STORES,
292   /* args: Bool. */
293
294   /* Set the name of the thread that performs this client request. */
295   VG_USERREQ__DRD_SET_THREAD_NAME,
296   /* args: null-terminated character string. */
297
298   /* Tell DRD to insert a happens before annotation. */
299   VG_USERREQ__DRD_ANNOTATE_HAPPENS_BEFORE,
300   /* args: Addr. */
301   /* Tell DRD to insert a happens after annotation. */
302   VG_USERREQ__DRD_ANNOTATE_HAPPENS_AFTER,
303   /* args: Addr. */
304
305   /* Tell DRD about an operation performed on a user-defined reader-writer
306    * synchronization object. */
307   VG_USERREQ__DRD_ANNOTATE_RWLOCK,
308   /* args: Addr, Int operation_type, Int is_rw. */
309};
310
311
312/*
313 * Do not call the inline functions below directly but use the macro's defined
314 * above. The names of these inline functions may change from one release to
315 * another.
316 */
317
318static __inline__
319void DRDCL_(clean_memory)(const void* const addr, const int size)
320{
321   int res;
322   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_CLEAN_MEMORY,
323                              addr, size, 0, 0, 0);
324}
325
326static __inline__
327int DRDCL_(get_valgrind_threadid)(void)
328{
329   int res;
330   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID,
331                              0, 0, 0, 0, 0);
332   return res;
333}
334
335static __inline__
336int DRDCL_(get_drd_threadid)(void)
337{
338   int res;
339   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_GET_DRD_THREAD_ID,
340                              0, 0, 0, 0, 0);
341   return res;
342}
343
344static __inline__
345void DRDCL_(ignore_range)(const void* const addr, const int size)
346{
347   int res;
348   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_START_SUPPRESSION,
349                              addr, size, 0, 0, 0);
350}
351
352static __inline__
353void DRDCL_(trace_range)(const void* const addr, const int size)
354{
355   int res;
356   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_START_TRACE_ADDR,
357                              addr, size, 0, 0, 0);
358}
359
360static __inline__
361void DRDCL_(set_record_loads)(const int enabled)
362{
363   int res;
364   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_RECORD_LOADS,
365                              enabled, 0, 0, 0, 0);
366}
367
368static __inline__
369void DRDCL_(set_record_stores)(const int enabled)
370{
371   int res;
372   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_RECORD_STORES,
373                              enabled, 0, 0, 0, 0);
374}
375
376static __inline__
377void DRDCL_(set_thread_name)(const char* const name)
378{
379   int res;
380   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_SET_THREAD_NAME,
381                              name, 0, 0, 0, 0);
382}
383
384static __inline__
385void DRDCL_(annotate_happens_before)(const void* const addr)
386{
387   int res;
388   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_ANNOTATE_HAPPENS_BEFORE,
389                              addr, 0, 0, 0, 0);
390}
391
392static __inline__
393void DRDCL_(annotate_happens_after)(const void* const addr)
394{
395   int res;
396   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_ANNOTATE_HAPPENS_AFTER,
397                              addr, 0, 0, 0, 0);
398}
399
400static __inline__
401void DRDCL_(annotate_rwlock)(const void* const rwlock, const int op,
402                             const int is_w)
403{
404   int res;
405   VALGRIND_DO_CLIENT_REQUEST(res, 0,
406                              VG_USERREQ__DRD_ANNOTATE_RWLOCK,
407                              rwlock, op, is_w, 0, 0);
408}
409
410#endif /* __VALGRIND_DRD_H */
411