Home | History | Annotate | Download | only in drd
      1 /* -*- mode: C; c-basic-offset: 3; indent-tabs-mode: nil; -*- */
      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-2011 Bart Van Assche <bvanassche (at) acm.org>.
     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 /** Obtain the thread ID assigned by Valgrind's core. */
     69 #define DRD_GET_VALGRIND_THREADID                                          \
     70     (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0,                           \
     71                                    VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID, \
     72                                    0, 0, 0, 0, 0)
     73 
     74 /** Obtain the thread ID assigned by DRD. */
     75 #define DRD_GET_DRD_THREADID                                            \
     76     (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0,                        \
     77                                    VG_USERREQ__DRD_GET_DRD_THREAD_ID,   \
     78                                    0, 0, 0, 0, 0)
     79 
     80 
     81 /** Tell DRD not to complain about data races for the specified variable. */
     82 #define DRD_IGNORE_VAR(x) ANNOTATE_BENIGN_RACE_SIZED(&(x), sizeof(x), "")
     83 
     84 /** Tell DRD to no longer ignore data races for the specified variable. */
     85 #define DRD_STOP_IGNORING_VAR(x)                                       \
     86    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_FINISH_SUPPRESSION, \
     87                                    &(x), sizeof(x), 0, 0, 0)
     88 
     89 /**
     90  * Tell DRD to trace all memory accesses on the specified variable.
     91  * until the memory that was allocated for the variable is freed.
     92  */
     93 #define DRD_TRACE_VAR(x)                                             \
     94    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_START_TRACE_ADDR, \
     95                                    &(x), sizeof(x), 0, 0, 0)
     96 
     97 /**
     98  * @defgroup RaceDetectionAnnotations Data race detection annotations.
     99  *
    100  * @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>
    101 
    102  * in the ThreadSanitizer project.
    103  */
    104 /*@{*/
    105 
    106 /**
    107  * Tell DRD to insert a happens-before mark. addr is the address of an object
    108  * that is not a pthread synchronization object.
    109  */
    110 #define ANNOTATE_HAPPENS_BEFORE(addr)                                       \
    111    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_HAPPENS_BEFORE, \
    112                                    addr, 0, 0, 0, 0)
    113 
    114 /**
    115  * Tell DRD that the memory accesses executed after this annotation will
    116  * happen after all memory accesses performed before all preceding
    117  * ANNOTATE_HAPPENS_BEFORE(addr). addr is the address of an object that is not
    118  * a pthread synchronization object. Inserting a happens-after annotation
    119  * before any other thread has passed by a happens-before annotation for the
    120  * same address is an error.
    121  */
    122 #define ANNOTATE_HAPPENS_AFTER(addr)                                       \
    123    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_HAPPENS_AFTER, \
    124                                    addr, 0, 0, 0, 0)
    125 
    126 /**
    127  * Tell DRD that waiting on the condition variable at address cv has succeeded
    128  * and a lock on the mutex at address mtx is now held. Since DRD always inserts
    129  * a happens before relation between the pthread_cond_signal() or
    130  * pthread_cond_broadcast() call that wakes up a pthread_cond_wait() or
    131  * pthread_cond_timedwait() call and the woken up thread, this macro has been
    132  * defined such that it has no effect.
    133  */
    134 #define ANNOTATE_CONDVAR_LOCK_WAIT(cv, mtx) do { } while(0)
    135 
    136 /**
    137  * Tell DRD that the condition variable at address cv is about to be signaled.
    138  */
    139 #define ANNOTATE_CONDVAR_SIGNAL(cv) do { } while(0)
    140 
    141 /**
    142  * Tell DRD that the condition variable at address cv is about to be signaled.
    143  */
    144 #define ANNOTATE_CONDVAR_SIGNAL_ALL(cv) do { } while(0)
    145 
    146 /**
    147  * Tell DRD that waiting on condition variable at address cv succeeded and that
    148  * the memory operations performed after this annotation should be considered
    149  * to happen after the matching ANNOTATE_CONDVAR_SIGNAL(cv). Since this is the
    150  * default behavior of DRD, this macro and the macro above have been defined
    151  * such that they have no effect.
    152  */
    153 #define ANNOTATE_CONDVAR_WAIT(cv) do { } while(0)
    154 
    155 /**
    156  * Tell DRD to consider the memory operations that happened before a mutex
    157  * unlock event and after the subsequent mutex lock event on the same mutex as
    158  * ordered. This is how DRD always behaves, so this macro has been defined
    159  * such that it has no effect.
    160  */
    161 #define ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mtx) do { } while(0)
    162 
    163 /** Deprecated -- don't use this annotation. */
    164 #define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mtx) do { } while(0)
    165 
    166 /**
    167  * Tell DRD to handle the specified memory range like a pure happens-before
    168  * detector would do. Since this is how DRD always behaves, this annotation
    169  * has been defined such that it has no effect.
    170  */
    171 #define ANNOTATE_PUBLISH_MEMORY_RANGE(addr, size) do { } while(0)
    172 
    173 /** Deprecated -- don't use this annotation. */
    174 #define ANNOTATE_UNPUBLISH_MEMORY_RANGE(addr, size) do { } while(0)
    175 
    176 /** Deprecated -- don't use this annotation. */
    177 #define ANNOTATE_SWAP_MEMORY_RANGE(addr, size) do { } while(0)
    178 
    179 /** Tell DRD that a reader-writer lock object has been initialized. */
    180 #define ANNOTATE_RWLOCK_CREATE(rwlock)                                     \
    181    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_RWLOCK_CREATE, \
    182                                    rwlock, 0, 0, 0, 0);
    183 
    184 /** Tell DRD that a reader-writer lock object has been destroyed. */
    185 #define ANNOTATE_RWLOCK_DESTROY(rwlock)                                     \
    186    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_RWLOCK_DESTROY, \
    187                                    rwlock, 0, 0, 0, 0);
    188 
    189 /**
    190  * Tell DRD that a reader-writer lock has been acquired. is_w == 1 means that
    191  * a write lock has been obtained, is_w == 0 means that a read lock has been
    192  * obtained.
    193  */
    194 #define ANNOTATE_RWLOCK_ACQUIRED(rwlock, is_w)                               \
    195    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_RWLOCK_ACQUIRED, \
    196                                    rwlock, is_w, 0, 0, 0)
    197 
    198 /**
    199  * Tell DRD that a reader lock has been acquired on a reader-writer
    200  * synchronization object.
    201  */
    202 #define ANNOTATE_READERLOCK_ACQUIRED(rwlock) ANNOTATE_RWLOCK_ACQUIRED(rwlock, 0)
    203 
    204 /**
    205  * Tell DRD that a writer lock has been acquired on a reader-writer
    206  * synchronization object.
    207  */
    208 #define ANNOTATE_WRITERLOCK_ACQUIRED(rwlock) ANNOTATE_RWLOCK_ACQUIRED(rwlock, 1)
    209 
    210 /**
    211  * Tell DRD that a reader-writer lock is about to be released. is_w == 1 means
    212  * that a write lock is about to be released, is_w == 0 means that a read lock
    213  * is about to be released.
    214  */
    215 #define ANNOTATE_RWLOCK_RELEASED(rwlock, is_w)                               \
    216    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_RWLOCK_RELEASED, \
    217                                    rwlock, is_w, 0, 0, 0);
    218 
    219 /**
    220  * Tell DRD that a reader lock is about to be released.
    221  */
    222 #define ANNOTATE_READERLOCK_RELEASED(rwlock) ANNOTATE_RWLOCK_RELEASED(rwlock, 0)
    223 
    224 /**
    225  * Tell DRD that a writer lock is about to be released.
    226  */
    227 #define ANNOTATE_WRITERLOCK_RELEASED(rwlock) ANNOTATE_RWLOCK_RELEASED(rwlock, 1)
    228 
    229 /*
    230  * Report that a barrier has been initialized with a given barrier count.  The
    231  * third argument specifies whether or not reinitialization is allowed, that
    232  * is, whether or not it is allowed to call barrier_init() several times
    233  * without calling barrier_destroy().
    234  */
    235 #define ANNOTATE_BARRIER_INIT(barrier, count, reinitialization_allowed) \
    236    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATION_UNIMP,    \
    237                                    "ANNOTATE_BARRIER_INIT", barrier,    \
    238                                    count, reinitialization_allowed, 0)
    239 
    240 /* Report that a barrier has been destroyed. */
    241 #define ANNOTATE_BARRIER_DESTROY(barrier)                               \
    242    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATION_UNIMP,    \
    243                                    "ANNOTATE_BARRIER_DESTROY",          \
    244                                    barrier, 0, 0, 0)
    245 
    246 /* Report that the calling thread is about to start waiting for a barrier. */
    247 #define ANNOTATE_BARRIER_WAIT_BEFORE(barrier)                           \
    248    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATION_UNIMP,    \
    249                                    "ANNOTATE_BARRIER_WAIT_BEFORE",      \
    250                                    barrier, 0, 0, 0)
    251 
    252 /* Report that the calling thread has just finished waiting for a barrier. */
    253 #define ANNOTATE_BARRIER_WAIT_AFTER(barrier)                            \
    254    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATION_UNIMP,    \
    255                                    "ANNOTATE_BARRIER_WAIT_AFTER",       \
    256                                    barrier, 0, 0, 0)
    257 
    258 /**
    259  * Tell DRD that a FIFO queue has been created. The abbreviation PCQ stands for
    260  * <em>producer-consumer</em>.
    261  */
    262 #define ANNOTATE_PCQ_CREATE(pcq) do { } while(0)
    263 
    264 /** Tell DRD that a FIFO queue has been destroyed. */
    265 #define ANNOTATE_PCQ_DESTROY(pcq) do { } while(0)
    266 
    267 /**
    268  * Tell DRD that an element has been added to the FIFO queue at address pcq.
    269  */
    270 #define ANNOTATE_PCQ_PUT(pcq) do { } while(0)
    271 
    272 /**
    273  * Tell DRD that an element has been removed from the FIFO queue at address pcq,
    274  * and that DRD should insert a happens-before relationship between the memory
    275  * accesses that occurred before the corresponding ANNOTATE_PCQ_PUT(pcq)
    276  * annotation and the memory accesses after this annotation. Correspondence
    277  * between PUT and GET annotations happens in FIFO order. Since locking
    278  * of the queue is needed anyway to add elements to or to remove elements from
    279  * the queue, for DRD all four FIFO annotations are defined as no-ops.
    280  */
    281 #define ANNOTATE_PCQ_GET(pcq) do { } while(0)
    282 
    283 /**
    284  * Tell DRD that data races at the specified address are expected and must not
    285  * be reported.
    286  */
    287 #define ANNOTATE_BENIGN_RACE(addr, descr) \
    288    ANNOTATE_BENIGN_RACE_SIZED(addr, sizeof(*addr), descr)
    289 
    290 /* Same as ANNOTATE_BENIGN_RACE(addr, descr), but applies to
    291    the memory range [addr, addr + size). */
    292 #define ANNOTATE_BENIGN_RACE_SIZED(addr, size, descr)                   \
    293    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_START_SUPPRESSION,   \
    294                                    addr, size, 0, 0, 0)
    295 
    296 /** Tell DRD to ignore all reads performed by the current thread. */
    297 #define ANNOTATE_IGNORE_READS_BEGIN()                                \
    298    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_RECORD_LOADS,     \
    299                                    0, 0, 0, 0, 0);
    300 
    301 
    302 /** Tell DRD to no longer ignore the reads performed by the current thread. */
    303 #define ANNOTATE_IGNORE_READS_END()                                  \
    304    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_RECORD_LOADS,     \
    305                                    1, 0, 0, 0, 0);
    306 
    307 /** Tell DRD to ignore all writes performed by the current thread. */
    308 #define ANNOTATE_IGNORE_WRITES_BEGIN()                                \
    309    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_RECORD_STORES,     \
    310                                    0, 0, 0, 0, 0)
    311 
    312 /** Tell DRD to no longer ignore the writes performed by the current thread. */
    313 #define ANNOTATE_IGNORE_WRITES_END()                                  \
    314    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_RECORD_STORES,     \
    315                                    1, 0, 0, 0, 0)
    316 
    317 /** Tell DRD to ignore all memory accesses performed by the current thread. */
    318 #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
    319    do { ANNOTATE_IGNORE_READS_BEGIN(); ANNOTATE_IGNORE_WRITES_BEGIN(); } while(0)
    320 
    321 /**
    322  * Tell DRD to no longer ignore the memory accesses performed by the current
    323  * thread.
    324  */
    325 #define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
    326    do { ANNOTATE_IGNORE_READS_END(); ANNOTATE_IGNORE_WRITES_END(); } while(0)
    327 
    328 /**
    329  * Tell DRD that size bytes starting at addr has been allocated by a custom
    330  * memory allocator.
    331  */
    332 #define ANNOTATE_NEW_MEMORY(addr, size)                           \
    333    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_CLEAN_MEMORY,  \
    334                                    addr, size, 0, 0, 0)
    335 
    336 /** Ask DRD to report every access to the specified address. */
    337 #define ANNOTATE_TRACE_MEMORY(addr) DRD_TRACE_VAR(*(char*)(addr))
    338 
    339 /**
    340  * Tell DRD to assign the specified name to the current thread. This name will
    341  * be used in error messages printed by DRD.
    342  */
    343 #define ANNOTATE_THREAD_NAME(name)                                      \
    344    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_SET_THREAD_NAME,     \
    345                                    name, 0, 0, 0, 0)
    346 
    347 /*@}*/
    348 
    349 
    350 /* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
    351    This enum comprises an ABI exported by Valgrind to programs
    352    which use client requests.  DO NOT CHANGE THE ORDER OF THESE
    353    ENTRIES, NOR DELETE ANY -- add new ones at the end.
    354 */
    355 enum {
    356    /* Ask the DRD tool to discard all information about memory accesses   */
    357    /* and client objects for the specified range. This client request is  */
    358    /* binary compatible with the similarly named Helgrind client request. */
    359    VG_USERREQ__DRD_CLEAN_MEMORY = VG_USERREQ_TOOL_BASE('H','G'),
    360    /* args: Addr, SizeT. */
    361 
    362    /* Ask the DRD tool the thread ID assigned by Valgrind. */
    363    VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID = VG_USERREQ_TOOL_BASE('D','R'),
    364    /* args: none. */
    365    /* Ask the DRD tool the thread ID assigned by DRD. */
    366    VG_USERREQ__DRD_GET_DRD_THREAD_ID,
    367    /* args: none. */
    368 
    369    /* To tell the DRD tool to suppress data race detection on the */
    370    /* specified address range. */
    371    VG_USERREQ__DRD_START_SUPPRESSION,
    372    /* args: start address, size in bytes */
    373    /* To tell the DRD tool no longer to suppress data race detection on */
    374    /* the specified address range. */
    375    VG_USERREQ__DRD_FINISH_SUPPRESSION,
    376    /* args: start address, size in bytes */
    377 
    378    /* To ask the DRD tool to trace all accesses to the specified range. */
    379    VG_USERREQ__DRD_START_TRACE_ADDR,
    380    /* args: Addr, SizeT. */
    381    /* To ask the DRD tool to stop tracing accesses to the specified range. */
    382    VG_USERREQ__DRD_STOP_TRACE_ADDR,
    383    /* args: Addr, SizeT. */
    384 
    385    /* Tell DRD whether or not to record memory loads in the calling thread. */
    386    VG_USERREQ__DRD_RECORD_LOADS,
    387    /* args: Bool. */
    388    /* Tell DRD whether or not to record memory stores in the calling thread. */
    389    VG_USERREQ__DRD_RECORD_STORES,
    390    /* args: Bool. */
    391 
    392    /* Set the name of the thread that performs this client request. */
    393    VG_USERREQ__DRD_SET_THREAD_NAME,
    394    /* args: null-terminated character string. */
    395 
    396    /* Tell DRD that a DRD annotation has not yet been implemented. */
    397    VG_USERREQ__DRD_ANNOTATION_UNIMP,
    398    /* args: Char*. */
    399 
    400    /* Tell DRD that a user-defined reader-writer synchronization object
    401     * has been created. */
    402    VG_USERREQ__DRD_ANNOTATE_RWLOCK_CREATE
    403       = VG_USERREQ_TOOL_BASE('H','G') + 256 + 14,
    404    /* args: Addr. */
    405    /* Tell DRD that a user-defined reader-writer synchronization object
    406     * is about to be destroyed. */
    407    VG_USERREQ__DRD_ANNOTATE_RWLOCK_DESTROY
    408       = VG_USERREQ_TOOL_BASE('H','G') + 256 + 15,
    409    /* args: Addr. */
    410    /* Tell DRD that a lock on a user-defined reader-writer synchronization
    411     * object has been acquired. */
    412    VG_USERREQ__DRD_ANNOTATE_RWLOCK_ACQUIRED
    413       = VG_USERREQ_TOOL_BASE('H','G') + 256 + 17,
    414    /* args: Addr, Int is_rw. */
    415    /* Tell DRD that a lock on a user-defined reader-writer synchronization
    416     * object is about to be released. */
    417    VG_USERREQ__DRD_ANNOTATE_RWLOCK_RELEASED
    418       = VG_USERREQ_TOOL_BASE('H','G') + 256 + 18,
    419    /* args: Addr, Int is_rw. */
    420 
    421    /* Tell DRD that a Helgrind annotation has not yet been implemented. */
    422    VG_USERREQ__HELGRIND_ANNOTATION_UNIMP
    423       = VG_USERREQ_TOOL_BASE('H','G') + 256 + 32,
    424    /* args: Char*. */
    425 
    426    /* Tell DRD to insert a happens-before annotation. */
    427    VG_USERREQ__DRD_ANNOTATE_HAPPENS_BEFORE
    428       = VG_USERREQ_TOOL_BASE('H','G') + 256 + 33,
    429    /* args: Addr. */
    430    /* Tell DRD to insert a happens-after annotation. */
    431    VG_USERREQ__DRD_ANNOTATE_HAPPENS_AFTER
    432       = VG_USERREQ_TOOL_BASE('H','G') + 256 + 34,
    433    /* args: Addr. */
    434 
    435 };
    436 
    437 
    438 /**
    439  * @addtogroup RaceDetectionAnnotations
    440  */
    441 /*@{*/
    442 
    443 #ifdef __cplusplus
    444 /* ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racy reads.
    445 
    446    Instead of doing
    447    ANNOTATE_IGNORE_READS_BEGIN();
    448    ... = x;
    449    ANNOTATE_IGNORE_READS_END();
    450    one can use
    451    ... = ANNOTATE_UNPROTECTED_READ(x); */
    452 template <typename T>
    453 inline T ANNOTATE_UNPROTECTED_READ(const volatile T& x) {
    454    ANNOTATE_IGNORE_READS_BEGIN();
    455    const T result = x;
    456    ANNOTATE_IGNORE_READS_END();
    457    return result;
    458 }
    459 /* Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable. */
    460 #define ANNOTATE_BENIGN_RACE_STATIC(static_var, description)		\
    461    namespace {								\
    462       static class static_var##_annotator				\
    463       {									\
    464       public:								\
    465 	 static_var##_annotator()					\
    466 	 {								\
    467 	    ANNOTATE_BENIGN_RACE_SIZED(&static_var, sizeof(static_var),	\
    468 				       #static_var ": " description);	\
    469 	 }								\
    470       } the_##static_var##_annotator;					\
    471    }
    472 #endif
    473 
    474 /*@}*/
    475 
    476 #endif /* __VALGRIND_DRD_H */
    477