Vendor valgrind headers
All checks were successful
Tests / Release [gcc] total: 583, passed: 583
GNU C Compiler (gcc) |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap: Reference build: <a href="https://jenkins.weaselab.dev/job/weaselab/job/conflict-set/job/main/31//gcc">weaselab » conflict-set » main #31</a>
Tests / Coverage total: 581, passed: 581
weaselab/conflict-set/pipeline/head This commit looks good

This is encouraged according to https://valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.clientreq
This commit is contained in:
2024-02-21 16:15:40 -08:00
parent 28e61340f4
commit 3750aa7b5b
10 changed files with 9197 additions and 23 deletions

View File

@@ -23,6 +23,10 @@ endif()
add_compile_options(-fdata-sections -ffunction-sections) add_compile_options(-fdata-sections -ffunction-sections)
# This is encouraged according to
# https://valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.clientreq
include_directories(SYSTEM ${CMAKE_SOURCE_DIR}/third_party/valgrind)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
add_compile_options(-Wno-maybe-uninitialized) add_compile_options(-Wno-maybe-uninitialized)
endif() endif()

View File

@@ -36,10 +36,7 @@ limitations under the License.
#include <arm_neon.h> #include <arm_neon.h>
#endif #endif
#if __has_include(<valgrind/memcheck.h>) #include <memcheck.h>
#define MEMCHECK
#include <valgrind/memcheck.h>
#endif
// ==================== BEGIN IMPLEMENTATION ==================== // ==================== BEGIN IMPLEMENTATION ====================
@@ -59,14 +56,10 @@ struct BoundedFreeListAllocator {
} }
assert(freeList != nullptr); assert(freeList != nullptr);
void *buffer = freeList; void *buffer = freeList;
#ifdef MEMCHECK
VALGRIND_MAKE_MEM_DEFINED(freeList, sizeof(freeList)); VALGRIND_MAKE_MEM_DEFINED(freeList, sizeof(freeList));
#endif
memcpy(&freeList, freeList, sizeof(freeList)); memcpy(&freeList, freeList, sizeof(freeList));
--freeListSize; --freeListSize;
#ifdef MEMCHECK
VALGRIND_MAKE_MEM_UNDEFINED(buffer, sizeof(T)); VALGRIND_MAKE_MEM_UNDEFINED(buffer, sizeof(T));
#endif
return new (buffer) T; return new (buffer) T;
} }
@@ -78,16 +71,12 @@ struct BoundedFreeListAllocator {
memcpy((void *)p, &freeList, sizeof(freeList)); memcpy((void *)p, &freeList, sizeof(freeList));
freeList = p; freeList = p;
++freeListSize; ++freeListSize;
#ifdef MEMCHECK
VALGRIND_MAKE_MEM_NOACCESS(p, sizeof(T)); VALGRIND_MAKE_MEM_NOACCESS(p, sizeof(T));
#endif
} }
~BoundedFreeListAllocator() { ~BoundedFreeListAllocator() {
for (void *iter = freeList; iter != nullptr;) { for (void *iter = freeList; iter != nullptr;) {
#ifdef MEMCHECK
VALGRIND_MAKE_MEM_DEFINED(iter, sizeof(iter)); VALGRIND_MAKE_MEM_DEFINED(iter, sizeof(iter));
#endif
auto *tmp = iter; auto *tmp = iter;
memcpy(&iter, iter, sizeof(void *)); memcpy(&iter, iter, sizeof(void *));
free(tmp); free(tmp);

View File

@@ -18,10 +18,7 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#if __has_include(<valgrind/callgrind.h>)
#define CALLGRIND
#include <valgrind/callgrind.h> #include <valgrind/callgrind.h>
#endif
#define DEBUG_VERBOSE 0 #define DEBUG_VERBOSE 0
@@ -562,13 +559,10 @@ template <class ConflictSetImpl> struct TestDriver {
assert(iter == keys.end()); assert(iter == keys.end());
assert(i == numPointWrites + numRangeWrites); assert(i == numPointWrites + numRangeWrites);
#ifdef CALLGRIND
CALLGRIND_START_INSTRUMENTATION; CALLGRIND_START_INSTRUMENTATION;
#endif
cs.addWrites(writes, numPointWrites + numRangeWrites); cs.addWrites(writes, numPointWrites + numRangeWrites);
#ifdef CALLGRIND
CALLGRIND_STOP_INSTRUMENTATION; CALLGRIND_STOP_INSTRUMENTATION;
#endif
refImpl.addWrites(writes, numPointWrites + numRangeWrites); refImpl.addWrites(writes, numPointWrites + numRangeWrites);
oldestVersion = std::max<int64_t>(writeVersion - arbitrary.bounded(10), oldestVersion = std::max<int64_t>(writeVersion - arbitrary.bounded(10),
@@ -635,13 +629,11 @@ template <class ConflictSetImpl> struct TestDriver {
new (arena) ConflictSet::Result[numPointReads + numRangeReads]; new (arena) ConflictSet::Result[numPointReads + numRangeReads];
auto *results2 = auto *results2 =
new (arena) ConflictSet::Result[numPointReads + numRangeReads]; new (arena) ConflictSet::Result[numPointReads + numRangeReads];
#ifdef CALLGRIND
CALLGRIND_START_INSTRUMENTATION; CALLGRIND_START_INSTRUMENTATION;
#endif
cs.check(reads, results1, numPointReads + numRangeReads); cs.check(reads, results1, numPointReads + numRangeReads);
#ifdef CALLGRIND
CALLGRIND_STOP_INSTRUMENTATION; CALLGRIND_STOP_INSTRUMENTATION;
#endif
refImpl.check(reads, results2, numPointReads + numRangeReads); refImpl.check(reads, results2, numPointReads + numRangeReads);
for (int i = 0; i < numPointReads + numRangeReads; ++i) { for (int i = 0; i < numPointReads + numRangeReads; ++i) {
if (results1[i] != results2[i]) { if (results1[i] != results2[i]) {

98
third_party/valgrind/cachegrind.h vendored Normal file
View File

@@ -0,0 +1,98 @@
/*
----------------------------------------------------------------
Notice that the following BSD-style license applies to this one
file (cachegrind.h) only. The rest of Valgrind is licensed under the
terms of the GNU General Public License, version 2, unless
otherwise indicated. See the COPYING file in the source
distribution for details.
----------------------------------------------------------------
This file is part of Cachegrind, a high-precision tracing profiler
built with Valgrind.
Copyright (C) 2023-2023 Nicholas Nethercote. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------
Notice that the above BSD-style license applies to this one file
(cachegrind.h) only. The entire rest of Valgrind is licensed under
the terms of the GNU General Public License, version 2. See the
COPYING file in the source distribution for details.
----------------------------------------------------------------
*/
#ifndef __CACHEGRIND_H
#define __CACHEGRIND_H
#include "valgrind.h"
/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
This enum comprises an ABI exported by Valgrind to programs
which use client requests. DO NOT CHANGE THE ORDER OF THESE
ENTRIES, NOR DELETE ANY -- add new ones at the end.
*/
typedef
enum {
/* The `CG_` is required to distinguish these from the Callgrind
* client requests of the same name. Otherwise compile errors occur if
* you include both `cachegrind.h` and `callgrind.h`.
*/
VG_USERREQ__CG_START_INSTRUMENTATION = VG_USERREQ_TOOL_BASE('C','G'),
VG_USERREQ__CG_STOP_INSTRUMENTATION
} Vg_CachegrindClientRequest;
/* Start Cachegrind instrumentation if not already enabled. Use this
* in combination with `CACHEGRIND_STOP_INSTRUMENTATION` and
* `--instr-at-start` to measure only part of a client program's
* execution.
*/
#define CACHEGRIND_START_INSTRUMENTATION \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CG_START_INSTRUMENTATION, \
0, 0, 0, 0, 0)
/* Stop Cachegrind instrumentation if not already disabled. Use this
* in combination with `CACHEGRIND_START_INSTRUMENTATION` and
* `--instr-at-start` to measure only part of a client program's
* execution.
*/
#define CACHEGRIND_STOP_INSTRUMENTATION \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CG_STOP_INSTRUMENTATION, \
0, 0, 0, 0, 0)
#endif /* __CACHEGRIND_H */

129
third_party/valgrind/callgrind.h vendored Normal file
View File

@@ -0,0 +1,129 @@
/*
----------------------------------------------------------------
Notice that the following BSD-style license applies to this one
file (callgrind.h) only. The rest of Valgrind is licensed under the
terms of the GNU General Public License, version 2, unless
otherwise indicated. See the COPYING file in the source
distribution for details.
----------------------------------------------------------------
This file is part of callgrind, a valgrind tool for cache simulation
and call tree tracing.
Copyright (C) 2003-2017 Josef Weidendorfer. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------
Notice that the above BSD-style license applies to this one file
(callgrind.h) only. The entire rest of Valgrind is licensed under
the terms of the GNU General Public License, version 2. See the
COPYING file in the source distribution for details.
----------------------------------------------------------------
*/
#ifndef __CALLGRIND_H
#define __CALLGRIND_H
#include "valgrind.h"
/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
This enum comprises an ABI exported by Valgrind to programs
which use client requests. DO NOT CHANGE THE ORDER OF THESE
ENTRIES, NOR DELETE ANY -- add new ones at the end.
The identification ('C','T') for Callgrind has historical
reasons: it was called "Calltree" before. Besides, ('C','G') would
clash with cachegrind.
*/
typedef
enum {
VG_USERREQ__DUMP_STATS = VG_USERREQ_TOOL_BASE('C','T'),
VG_USERREQ__ZERO_STATS,
VG_USERREQ__TOGGLE_COLLECT,
VG_USERREQ__DUMP_STATS_AT,
VG_USERREQ__START_INSTRUMENTATION,
VG_USERREQ__STOP_INSTRUMENTATION
} Vg_CallgrindClientRequest;
/* Dump current state of cost centers, and zero them afterwards */
#define CALLGRIND_DUMP_STATS \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DUMP_STATS, \
0, 0, 0, 0, 0)
/* Dump current state of cost centers, and zero them afterwards.
The argument is appended to a string stating the reason which triggered
the dump. This string is written as a description field into the
profile data dump. */
#define CALLGRIND_DUMP_STATS_AT(pos_str) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DUMP_STATS_AT, \
pos_str, 0, 0, 0, 0)
/* Zero cost centers */
#define CALLGRIND_ZERO_STATS \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__ZERO_STATS, \
0, 0, 0, 0, 0)
/* Toggles collection state.
The collection state specifies whether the happening of events
should be noted or if they are to be ignored. Events are noted
by increment of counters in a cost center */
#define CALLGRIND_TOGGLE_COLLECT \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TOGGLE_COLLECT, \
0, 0, 0, 0, 0)
/* Start full callgrind instrumentation if not already switched on.
When cache simulation is done, it will flush the simulated cache;
this will lead to an artificial cache warmup phase afterwards with
cache misses which would not have happened in reality. */
#define CALLGRIND_START_INSTRUMENTATION \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__START_INSTRUMENTATION, \
0, 0, 0, 0, 0)
/* Stop full callgrind instrumentation if not already switched off.
This flushes Valgrinds translation cache, and does no additional
instrumentation afterwards, which effectivly will run at the same
speed as the "none" tool (ie. at minimal slowdown).
Use this to bypass Callgrind aggregation for uninteresting code parts.
To start Callgrind in this mode to ignore the setup phase, use
the option "--instr-atstart=no". */
#define CALLGRIND_STOP_INSTRUMENTATION \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STOP_INSTRUMENTATION, \
0, 0, 0, 0, 0)
#endif /* __CALLGRIND_H */

86
third_party/valgrind/dhat.h vendored Normal file
View File

@@ -0,0 +1,86 @@
/*
----------------------------------------------------------------
Notice that the following BSD-style license applies to this one
file (dhat.h) only. The rest of Valgrind is licensed under the
terms of the GNU General Public License, version 2, unless
otherwise indicated. See the COPYING file in the source
distribution for details.
----------------------------------------------------------------
This file is part of DHAT, a Valgrind tool for profiling the
heap usage of programs.
Copyright (C) 2020 Nicholas Nethercote. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------
Notice that the above BSD-style license applies to this one file
(memcheck.h) only. The entire rest of Valgrind is licensed under
the terms of the GNU General Public License, version 2. See the
COPYING file in the source distribution for details.
----------------------------------------------------------------
*/
#if !defined(VALGRIND_DHAT_H)
#define VALGRIND_DHAT_H
#include "valgrind.h"
typedef
enum {
VG_USERREQ__DHAT_AD_HOC_EVENT = VG_USERREQ_TOOL_BASE('D', 'H'),
VG_USERREQ__DHAT_HISTOGRAM_MEMORY,
// This is just for DHAT's internal use. Don't use it.
_VG_USERREQ__DHAT_COPY = VG_USERREQ_TOOL_BASE('D','H') + 256
} Vg_DHATClientRequest;
// Record an ad hoc event. The meaning of the weight argument will depend on
// what the event represents, which is up to the user. If no meaningful weight
// argument exists, just use 1.
#define DHAT_AD_HOC_EVENT(_qzz_weight) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DHAT_AD_HOC_EVENT, \
(_qzz_weight), 0, 0, 0, 0)
// for access count histograms of memory larger than 1k
#define DHAT_HISTOGRAM_MEMORY(_qzz_address) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DHAT_HISTOGRAM_MEMORY, \
(_qzz_address), 0, 0, 0, 0)
#endif

571
third_party/valgrind/drd.h vendored Normal file
View File

@@ -0,0 +1,571 @@
/*
----------------------------------------------------------------
Notice that the following BSD-style license applies to this one
file (drd.h) only. The rest of Valgrind is licensed under the
terms of the GNU General Public License, version 2, unless
otherwise indicated. See the COPYING file in the source
distribution for details.
----------------------------------------------------------------
This file is part of DRD, a Valgrind tool for verification of
multithreaded programs.
Copyright (C) 2006-2020 Bart Van Assche <bvanassche@acm.org>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------
Notice that the above BSD-style license applies to this one file
(drd.h) only. The entire rest of Valgrind is licensed under
the terms of the GNU General Public License, version 2. See the
COPYING file in the source distribution for details.
----------------------------------------------------------------
*/
#ifndef __VALGRIND_DRD_H
#define __VALGRIND_DRD_H
#include "valgrind.h"
/** Obtain the thread ID assigned by Valgrind's core. */
#define DRD_GET_VALGRIND_THREADID \
(unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID, \
0, 0, 0, 0, 0)
/** Obtain the thread ID assigned by DRD. */
#define DRD_GET_DRD_THREADID \
(unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
VG_USERREQ__DRD_GET_DRD_THREAD_ID, \
0, 0, 0, 0, 0)
/** Tell DRD not to complain about data races for the specified variable. */
#define DRD_IGNORE_VAR(x) ANNOTATE_BENIGN_RACE_SIZED(&(x), sizeof(x), "")
/** Tell DRD to no longer ignore data races for the specified variable. */
#define DRD_STOP_IGNORING_VAR(x) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_FINISH_SUPPRESSION, \
&(x), sizeof(x), 0, 0, 0)
/**
* Tell DRD to trace all memory accesses for the specified variable
* until the memory that was allocated for the variable is freed.
*/
#define DRD_TRACE_VAR(x) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_START_TRACE_ADDR, \
&(x), sizeof(x), 0, 0, 0)
/**
* Tell DRD to stop tracing memory accesses for the specified variable.
*/
#define DRD_STOP_TRACING_VAR(x) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_STOP_TRACE_ADDR, \
&(x), sizeof(x), 0, 0, 0)
/**
* @defgroup RaceDetectionAnnotations Data race detection annotations.
*
* @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>
* in the ThreadSanitizer project.
*/
/*@{*/
#ifndef __HELGRIND_H
/**
* Tell DRD to insert a happens-before mark. addr is the address of an object
* that is not a pthread synchronization object.
*/
#define ANNOTATE_HAPPENS_BEFORE(addr) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_HAPPENS_BEFORE, \
addr, 0, 0, 0, 0)
/**
* Tell DRD that the memory accesses executed after this annotation will
* happen after all memory accesses performed before all preceding
* ANNOTATE_HAPPENS_BEFORE(addr). addr is the address of an object that is not
* a pthread synchronization object. Inserting a happens-after annotation
* before any other thread has passed by a happens-before annotation for the
* same address is an error.
*/
#define ANNOTATE_HAPPENS_AFTER(addr) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_HAPPENS_AFTER, \
addr, 0, 0, 0, 0)
#else /* __HELGRIND_H */
#undef ANNOTATE_CONDVAR_LOCK_WAIT
#undef ANNOTATE_CONDVAR_WAIT
#undef ANNOTATE_CONDVAR_SIGNAL
#undef ANNOTATE_CONDVAR_SIGNAL_ALL
#undef ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX
#undef ANNOTATE_PUBLISH_MEMORY_RANGE
#undef ANNOTATE_BARRIER_INIT
#undef ANNOTATE_BARRIER_WAIT_BEFORE
#undef ANNOTATE_BARRIER_WAIT_AFTER
#undef ANNOTATE_BARRIER_DESTROY
#undef ANNOTATE_PCQ_CREATE
#undef ANNOTATE_PCQ_DESTROY
#undef ANNOTATE_PCQ_PUT
#undef ANNOTATE_PCQ_GET
#undef ANNOTATE_BENIGN_RACE
#undef ANNOTATE_BENIGN_RACE_SIZED
#undef ANNOTATE_IGNORE_READS_BEGIN
#undef ANNOTATE_IGNORE_READS_END
#undef ANNOTATE_IGNORE_WRITES_BEGIN
#undef ANNOTATE_IGNORE_WRITES_END
#undef ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN
#undef ANNOTATE_IGNORE_READS_AND_WRITES_END
#undef ANNOTATE_NEW_MEMORY
#undef ANNOTATE_TRACE_MEMORY
#undef ANNOTATE_THREAD_NAME
#endif /* __HELGRIND_H */
/**
* Tell DRD that waiting on the condition variable at address cv has succeeded
* and a lock on the mutex at address mtx is now held. Since DRD always inserts
* a happens before relation between the pthread_cond_signal() or
* pthread_cond_broadcast() call that wakes up a pthread_cond_wait() or
* pthread_cond_timedwait() call and the woken up thread, this macro has been
* defined such that it has no effect.
*/
#define ANNOTATE_CONDVAR_LOCK_WAIT(cv, mtx) do { } while(0)
/**
* Tell DRD that the condition variable at address cv is about to be signaled.
*/
#define ANNOTATE_CONDVAR_SIGNAL(cv) do { } while(0)
/**
* Tell DRD that the condition variable at address cv is about to be signaled.
*/
#define ANNOTATE_CONDVAR_SIGNAL_ALL(cv) do { } while(0)
/**
* Tell DRD that waiting on condition variable at address cv succeeded and that
* the memory operations performed after this annotation should be considered
* to happen after the matching ANNOTATE_CONDVAR_SIGNAL(cv). Since this is the
* default behavior of DRD, this macro and the macro above have been defined
* such that they have no effect.
*/
#define ANNOTATE_CONDVAR_WAIT(cv) do { } while(0)
/**
* Tell DRD to consider the memory operations that happened before a mutex
* unlock event and after the subsequent mutex lock event on the same mutex as
* ordered. This is how DRD always behaves, so this macro has been defined
* such that it has no effect.
*/
#define ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mtx) do { } while(0)
/** Deprecated -- don't use this annotation. */
#define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mtx) do { } while(0)
/**
* Tell DRD to handle the specified memory range like a pure happens-before
* detector would do. Since this is how DRD always behaves, this annotation
* has been defined such that it has no effect.
*/
#define ANNOTATE_PUBLISH_MEMORY_RANGE(addr, size) do { } while(0)
/** Deprecated -- don't use this annotation. */
#define ANNOTATE_UNPUBLISH_MEMORY_RANGE(addr, size) do { } while(0)
/** Deprecated -- don't use this annotation. */
#define ANNOTATE_SWAP_MEMORY_RANGE(addr, size) do { } while(0)
#ifndef __HELGRIND_H
/** Tell DRD that a reader-writer lock object has been initialized. */
#define ANNOTATE_RWLOCK_CREATE(rwlock) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_RWLOCK_CREATE, \
rwlock, 0, 0, 0, 0);
/** Tell DRD that a reader-writer lock object has been destroyed. */
#define ANNOTATE_RWLOCK_DESTROY(rwlock) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_RWLOCK_DESTROY, \
rwlock, 0, 0, 0, 0);
/**
* Tell DRD that a reader-writer lock has been acquired. is_w == 1 means that
* a write lock has been obtained, is_w == 0 means that a read lock has been
* obtained.
*/
#define ANNOTATE_RWLOCK_ACQUIRED(rwlock, is_w) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_RWLOCK_ACQUIRED, \
rwlock, is_w, 0, 0, 0)
#endif /* __HELGRIND_H */
/**
* Tell DRD that a reader lock has been acquired on a reader-writer
* synchronization object.
*/
#define ANNOTATE_READERLOCK_ACQUIRED(rwlock) ANNOTATE_RWLOCK_ACQUIRED(rwlock, 0)
/**
* Tell DRD that a writer lock has been acquired on a reader-writer
* synchronization object.
*/
#define ANNOTATE_WRITERLOCK_ACQUIRED(rwlock) ANNOTATE_RWLOCK_ACQUIRED(rwlock, 1)
#ifndef __HELGRIND_H
/**
* Tell DRD that a reader-writer lock is about to be released. is_w == 1 means
* that a write lock is about to be released, is_w == 0 means that a read lock
* is about to be released.
*/
#define ANNOTATE_RWLOCK_RELEASED(rwlock, is_w) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_RWLOCK_RELEASED, \
rwlock, is_w, 0, 0, 0);
#endif /* __HELGRIND_H */
/**
* Tell DRD that a reader lock is about to be released.
*/
#define ANNOTATE_READERLOCK_RELEASED(rwlock) ANNOTATE_RWLOCK_RELEASED(rwlock, 0)
/**
* Tell DRD that a writer lock is about to be released.
*/
#define ANNOTATE_WRITERLOCK_RELEASED(rwlock) ANNOTATE_RWLOCK_RELEASED(rwlock, 1)
/** Tell DRD that a semaphore object is going to be initialized. */
#define ANNOTATE_SEM_INIT_PRE(sem, value) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_SEM_INIT_PRE, \
sem, value, 0, 0, 0);
/** Tell DRD that a semaphore object has been destroyed. */
#define ANNOTATE_SEM_DESTROY_POST(sem) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_SEM_DESTROY_POST, \
sem, 0, 0, 0, 0);
/** Tell DRD that a semaphore is going to be acquired. */
#define ANNOTATE_SEM_WAIT_PRE(sem) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_SEM_WAIT_PRE, \
sem, 0, 0, 0, 0)
/** Tell DRD that a semaphore has been acquired. */
#define ANNOTATE_SEM_WAIT_POST(sem) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_SEM_WAIT_POST, \
sem, 0, 0, 0, 0)
/** Tell DRD that a semaphore is going to be released. */
#define ANNOTATE_SEM_POST_PRE(sem) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATE_SEM_POST_PRE, \
sem, 0, 0, 0, 0)
/*
* Report that a barrier has been initialized with a given barrier count. The
* third argument specifies whether or not reinitialization is allowed, that
* is, whether or not it is allowed to call barrier_init() several times
* without calling barrier_destroy().
*/
#define ANNOTATE_BARRIER_INIT(barrier, count, reinitialization_allowed) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATION_UNIMP, \
"ANNOTATE_BARRIER_INIT", barrier, \
count, reinitialization_allowed, 0)
/* Report that a barrier has been destroyed. */
#define ANNOTATE_BARRIER_DESTROY(barrier) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATION_UNIMP, \
"ANNOTATE_BARRIER_DESTROY", \
barrier, 0, 0, 0)
/* Report that the calling thread is about to start waiting for a barrier. */
#define ANNOTATE_BARRIER_WAIT_BEFORE(barrier) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATION_UNIMP, \
"ANNOTATE_BARRIER_WAIT_BEFORE", \
barrier, 0, 0, 0)
/* Report that the calling thread has just finished waiting for a barrier. */
#define ANNOTATE_BARRIER_WAIT_AFTER(barrier) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_ANNOTATION_UNIMP, \
"ANNOTATE_BARRIER_WAIT_AFTER", \
barrier, 0, 0, 0)
/**
* Tell DRD that a FIFO queue has been created. The abbreviation PCQ stands for
* <em>producer-consumer</em>.
*/
#define ANNOTATE_PCQ_CREATE(pcq) do { } while(0)
/** Tell DRD that a FIFO queue has been destroyed. */
#define ANNOTATE_PCQ_DESTROY(pcq) do { } while(0)
/**
* Tell DRD that an element has been added to the FIFO queue at address pcq.
*/
#define ANNOTATE_PCQ_PUT(pcq) do { } while(0)
/**
* Tell DRD that an element has been removed from the FIFO queue at address pcq,
* and that DRD should insert a happens-before relationship between the memory
* accesses that occurred before the corresponding ANNOTATE_PCQ_PUT(pcq)
* annotation and the memory accesses after this annotation. Correspondence
* between PUT and GET annotations happens in FIFO order. Since locking
* of the queue is needed anyway to add elements to or to remove elements from
* the queue, for DRD all four FIFO annotations are defined as no-ops.
*/
#define ANNOTATE_PCQ_GET(pcq) do { } while(0)
/**
* Tell DRD that data races at the specified address are expected and must not
* be reported.
*/
#define ANNOTATE_BENIGN_RACE(addr, descr) \
ANNOTATE_BENIGN_RACE_SIZED(addr, sizeof(*addr), descr)
/* Same as ANNOTATE_BENIGN_RACE(addr, descr), but applies to
the memory range [addr, addr + size). */
#define ANNOTATE_BENIGN_RACE_SIZED(addr, size, descr) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_START_SUPPRESSION, \
addr, size, 0, 0, 0)
/** Tell DRD to ignore all reads performed by the current thread. */
#define ANNOTATE_IGNORE_READS_BEGIN() \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_RECORD_LOADS, \
0, 0, 0, 0, 0);
/** Tell DRD to no longer ignore the reads performed by the current thread. */
#define ANNOTATE_IGNORE_READS_END() \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_RECORD_LOADS, \
1, 0, 0, 0, 0);
/** Tell DRD to ignore all writes performed by the current thread. */
#define ANNOTATE_IGNORE_WRITES_BEGIN() \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_RECORD_STORES, \
0, 0, 0, 0, 0)
/** Tell DRD to no longer ignore the writes performed by the current thread. */
#define ANNOTATE_IGNORE_WRITES_END() \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_RECORD_STORES, \
1, 0, 0, 0, 0)
/** Tell DRD to ignore all memory accesses performed by the current thread. */
#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
do { ANNOTATE_IGNORE_READS_BEGIN(); ANNOTATE_IGNORE_WRITES_BEGIN(); } while(0)
/**
* Tell DRD to no longer ignore the memory accesses performed by the current
* thread.
*/
#define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
do { ANNOTATE_IGNORE_READS_END(); ANNOTATE_IGNORE_WRITES_END(); } while(0)
/**
* Tell DRD that size bytes starting at addr has been allocated by a custom
* memory allocator.
*/
#define ANNOTATE_NEW_MEMORY(addr, size) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_CLEAN_MEMORY, \
addr, size, 0, 0, 0)
/** Ask DRD to report every access to the specified address. */
#define ANNOTATE_TRACE_MEMORY(addr) DRD_TRACE_VAR(*(char*)(addr))
/**
* Tell DRD to assign the specified name to the current thread. This name will
* be used in error messages printed by DRD.
*/
#define ANNOTATE_THREAD_NAME(name) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_SET_THREAD_NAME, \
name, 0, 0, 0, 0)
/*@}*/
/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
This enum comprises an ABI exported by Valgrind to programs
which use client requests. DO NOT CHANGE THE ORDER OF THESE
ENTRIES, NOR DELETE ANY -- add new ones at the end.
*/
enum {
/* Ask the DRD tool to discard all information about memory accesses */
/* and client objects for the specified range. This client request is */
/* binary compatible with the similarly named Helgrind client request. */
VG_USERREQ__DRD_CLEAN_MEMORY = VG_USERREQ_TOOL_BASE('H','G'),
/* args: Addr, SizeT. */
/* Ask the DRD tool the thread ID assigned by Valgrind. */
VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID = VG_USERREQ_TOOL_BASE('D','R'),
/* args: none. */
/* Ask the DRD tool the thread ID assigned by DRD. */
VG_USERREQ__DRD_GET_DRD_THREAD_ID,
/* args: none. */
/* To tell the DRD tool to suppress data race detection on the */
/* specified address range. */
VG_USERREQ__DRD_START_SUPPRESSION,
/* args: start address, size in bytes */
/* To tell the DRD tool no longer to suppress data race detection on */
/* the specified address range. */
VG_USERREQ__DRD_FINISH_SUPPRESSION,
/* args: start address, size in bytes */
/* To ask the DRD tool to trace all accesses to the specified range. */
VG_USERREQ__DRD_START_TRACE_ADDR,
/* args: Addr, SizeT. */
/* To ask the DRD tool to stop tracing accesses to the specified range. */
VG_USERREQ__DRD_STOP_TRACE_ADDR,
/* args: Addr, SizeT. */
/* Tell DRD whether or not to record memory loads in the calling thread. */
VG_USERREQ__DRD_RECORD_LOADS,
/* args: Bool. */
/* Tell DRD whether or not to record memory stores in the calling thread. */
VG_USERREQ__DRD_RECORD_STORES,
/* args: Bool. */
/* Set the name of the thread that performs this client request. */
VG_USERREQ__DRD_SET_THREAD_NAME,
/* args: null-terminated character string. */
/* Tell DRD that a DRD annotation has not yet been implemented. */
VG_USERREQ__DRD_ANNOTATION_UNIMP,
/* args: char*. */
/* Tell DRD that a user-defined semaphore synchronization object
* is about to be created. */
VG_USERREQ__DRD_ANNOTATE_SEM_INIT_PRE,
/* args: Addr, UInt value. */
/* Tell DRD that a user-defined semaphore synchronization object
* has been destroyed. */
VG_USERREQ__DRD_ANNOTATE_SEM_DESTROY_POST,
/* args: Addr. */
/* Tell DRD that a user-defined semaphore synchronization
* object is going to be acquired (semaphore wait). */
VG_USERREQ__DRD_ANNOTATE_SEM_WAIT_PRE,
/* args: Addr. */
/* Tell DRD that a user-defined semaphore synchronization
* object has been acquired (semaphore wait). */
VG_USERREQ__DRD_ANNOTATE_SEM_WAIT_POST,
/* args: Addr. */
/* Tell DRD that a user-defined semaphore synchronization
* object is about to be released (semaphore post). */
VG_USERREQ__DRD_ANNOTATE_SEM_POST_PRE,
/* args: Addr. */
/* Tell DRD to ignore the inter-thread ordering introduced by a mutex. */
VG_USERREQ__DRD_IGNORE_MUTEX_ORDERING,
/* args: Addr. */
/* Tell DRD that a user-defined reader-writer synchronization object
* has been created. */
VG_USERREQ__DRD_ANNOTATE_RWLOCK_CREATE
= VG_USERREQ_TOOL_BASE('H','G') + 256 + 14,
/* args: Addr. */
/* Tell DRD that a user-defined reader-writer synchronization object
* is about to be destroyed. */
VG_USERREQ__DRD_ANNOTATE_RWLOCK_DESTROY
= VG_USERREQ_TOOL_BASE('H','G') + 256 + 15,
/* args: Addr. */
/* Tell DRD that a lock on a user-defined reader-writer synchronization
* object has been acquired. */
VG_USERREQ__DRD_ANNOTATE_RWLOCK_ACQUIRED
= VG_USERREQ_TOOL_BASE('H','G') + 256 + 17,
/* args: Addr, Int is_rw. */
/* Tell DRD that a lock on a user-defined reader-writer synchronization
* object is about to be released. */
VG_USERREQ__DRD_ANNOTATE_RWLOCK_RELEASED
= VG_USERREQ_TOOL_BASE('H','G') + 256 + 18,
/* args: Addr, Int is_rw. */
/* Tell DRD that a Helgrind annotation has not yet been implemented. */
VG_USERREQ__HELGRIND_ANNOTATION_UNIMP
= VG_USERREQ_TOOL_BASE('H','G') + 256 + 32,
/* args: char*. */
/* Tell DRD to insert a happens-before annotation. */
VG_USERREQ__DRD_ANNOTATE_HAPPENS_BEFORE
= VG_USERREQ_TOOL_BASE('H','G') + 256 + 33,
/* args: Addr. */
/* Tell DRD to insert a happens-after annotation. */
VG_USERREQ__DRD_ANNOTATE_HAPPENS_AFTER
= VG_USERREQ_TOOL_BASE('H','G') + 256 + 34,
/* args: Addr. */
};
/**
* @addtogroup RaceDetectionAnnotations
*/
/*@{*/
#ifdef __cplusplus
/* ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racy reads.
Instead of doing
ANNOTATE_IGNORE_READS_BEGIN();
... = x;
ANNOTATE_IGNORE_READS_END();
one can use
... = ANNOTATE_UNPROTECTED_READ(x); */
template <typename T>
inline T ANNOTATE_UNPROTECTED_READ(const volatile T& x) {
ANNOTATE_IGNORE_READS_BEGIN();
const T result = x;
ANNOTATE_IGNORE_READS_END();
return result;
}
/* Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable. */
#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \
namespace { \
static class static_var##_annotator \
{ \
public: \
static_var##_annotator() \
{ \
ANNOTATE_BENIGN_RACE_SIZED(&static_var, sizeof(static_var), \
#static_var ": " description); \
} \
} the_##static_var##_annotator; \
}
#endif
/*@}*/
#endif /* __VALGRIND_DRD_H */

830
third_party/valgrind/helgrind.h vendored Normal file
View File

@@ -0,0 +1,830 @@
/*
----------------------------------------------------------------
Notice that the above BSD-style license applies to this one file
(helgrind.h) only. The entire rest of Valgrind is licensed under
the terms of the GNU General Public License, version 2. See the
COPYING file in the source distribution for details.
----------------------------------------------------------------
This file is part of Helgrind, a Valgrind tool for detecting errors
in threaded programs.
Copyright (C) 2007-2017 OpenWorks LLP
info@open-works.co.uk
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------
Notice that the above BSD-style license applies to this one file
(helgrind.h) only. The entire rest of Valgrind is licensed under
the terms of the GNU General Public License, version 2. See the
COPYING file in the source distribution for details.
----------------------------------------------------------------
*/
#ifndef __HELGRIND_H
#define __HELGRIND_H
#include "valgrind.h"
/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
This enum comprises an ABI exported by Valgrind to programs
which use client requests. DO NOT CHANGE THE ORDER OF THESE
ENTRIES, NOR DELETE ANY -- add new ones at the end. */
typedef
enum {
VG_USERREQ__HG_CLEAN_MEMORY = VG_USERREQ_TOOL_BASE('H','G'),
/* The rest are for Helgrind's internal use. Not for end-user
use. Do not use them unless you are a Valgrind developer. */
/* Notify the tool what this thread's pthread_t is. */
_VG_USERREQ__HG_SET_MY_PTHREAD_T = VG_USERREQ_TOOL_BASE('H','G')
+ 256,
_VG_USERREQ__HG_PTH_API_ERROR, /* char*, int */
_VG_USERREQ__HG_PTHREAD_JOIN_POST, /* pthread_t of quitter */
_VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST, /* pth_mx_t*, long mbRec */
_VG_USERREQ__HG_PTHREAD_MUTEX_DESTROY_PRE, /* pth_mx_t*, long isInit */
_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE, /* pth_mx_t* */
_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST, /* pth_mx_t* */
_VG_USERREQ__HG_PTHREAD_MUTEX_ACQUIRE_PRE, /* void*, long isTryLock */
_VG_USERREQ__HG_PTHREAD_MUTEX_ACQUIRE_POST, /* void* */
_VG_USERREQ__HG_PTHREAD_COND_SIGNAL_PRE, /* pth_cond_t* */
_VG_USERREQ__HG_PTHREAD_COND_BROADCAST_PRE, /* pth_cond_t* */
_VG_USERREQ__HG_PTHREAD_COND_WAIT_PRE, /* pth_cond_t*, pth_mx_t* */
_VG_USERREQ__HG_PTHREAD_COND_WAIT_POST, /* pth_cond_t*, pth_mx_t* */
_VG_USERREQ__HG_PTHREAD_COND_DESTROY_PRE, /* pth_cond_t*, long isInit */
_VG_USERREQ__HG_PTHREAD_RWLOCK_INIT_POST, /* pth_rwlk_t* */
_VG_USERREQ__HG_PTHREAD_RWLOCK_DESTROY_PRE, /* pth_rwlk_t* */
_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE, /* pth_rwlk_t*, long isW */
_VG_USERREQ__HG_PTHREAD_RWLOCK_ACQUIRED, /* void*, long isW */
_VG_USERREQ__HG_PTHREAD_RWLOCK_RELEASED, /* void* */
_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_POST, /* pth_rwlk_t* */
_VG_USERREQ__HG_POSIX_SEM_INIT_POST, /* sem_t*, ulong value */
_VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE, /* sem_t* */
_VG_USERREQ__HG_POSIX_SEM_RELEASED, /* void* */
_VG_USERREQ__HG_POSIX_SEM_ACQUIRED, /* void* */
_VG_USERREQ__HG_PTHREAD_BARRIER_INIT_PRE, /* pth_bar_t*, ulong, ulong */
_VG_USERREQ__HG_PTHREAD_BARRIER_WAIT_PRE, /* pth_bar_t* */
_VG_USERREQ__HG_PTHREAD_BARRIER_DESTROY_PRE, /* pth_bar_t* */
_VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_PRE, /* pth_slk_t* */
_VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_POST, /* pth_slk_t* */
_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_PRE, /* pth_slk_t* */
_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_POST, /* pth_slk_t* */
_VG_USERREQ__HG_PTHREAD_SPIN_DESTROY_PRE, /* pth_slk_t* */
_VG_USERREQ__HG_CLIENTREQ_UNIMP, /* char* */
_VG_USERREQ__HG_USERSO_SEND_PRE, /* arbitrary UWord SO-tag */
_VG_USERREQ__HG_USERSO_RECV_POST, /* arbitrary UWord SO-tag */
_VG_USERREQ__HG_USERSO_FORGET_ALL, /* arbitrary UWord SO-tag */
_VG_USERREQ__HG_RESERVED2, /* Do not use */
_VG_USERREQ__HG_RESERVED3, /* Do not use */
_VG_USERREQ__HG_RESERVED4, /* Do not use */
_VG_USERREQ__HG_ARANGE_MAKE_UNTRACKED, /* Addr a, ulong len */
_VG_USERREQ__HG_ARANGE_MAKE_TRACKED, /* Addr a, ulong len */
_VG_USERREQ__HG_PTHREAD_BARRIER_RESIZE_PRE, /* pth_bar_t*, ulong */
_VG_USERREQ__HG_CLEAN_MEMORY_HEAPBLOCK, /* Addr start_of_block */
_VG_USERREQ__HG_PTHREAD_COND_INIT_POST, /* pth_cond_t*, pth_cond_attr_t*/
_VG_USERREQ__HG_GNAT_MASTER_HOOK, /* void*d,void*m,Word ml */
_VG_USERREQ__HG_GNAT_MASTER_COMPLETED_HOOK, /* void*s,Word ml */
_VG_USERREQ__HG_GET_ABITS, /* Addr a,Addr abits, ulong len */
_VG_USERREQ__HG_PTHREAD_CREATE_BEGIN,
_VG_USERREQ__HG_PTHREAD_CREATE_END,
_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE, /* pth_mx_t*,long isTryLock */
_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST, /* pth_mx_t *,long tookLock */
_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST, /* pth_rwlk_t*,long isW,long */
_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_PRE, /* pth_rwlk_t* */
_VG_USERREQ__HG_POSIX_SEM_POST_PRE, /* sem_t* */
_VG_USERREQ__HG_POSIX_SEM_POST_POST, /* sem_t* */
_VG_USERREQ__HG_POSIX_SEM_WAIT_PRE, /* sem_t* */
_VG_USERREQ__HG_POSIX_SEM_WAIT_POST, /* sem_t*, long tookLock */
_VG_USERREQ__HG_PTHREAD_COND_SIGNAL_POST, /* pth_cond_t* */
_VG_USERREQ__HG_PTHREAD_COND_BROADCAST_POST,/* pth_cond_t* */
_VG_USERREQ__HG_RTLD_BIND_GUARD, /* int flags */
_VG_USERREQ__HG_RTLD_BIND_CLEAR, /* int flags */
_VG_USERREQ__HG_GNAT_DEPENDENT_MASTER_JOIN /* void*d, void*m */
} Vg_TCheckClientRequest;
/*----------------------------------------------------------------*/
/*--- ---*/
/*--- Implementation-only facilities. Not for end-user use. ---*/
/*--- For end-user facilities see below (the next section in ---*/
/*--- this file.) ---*/
/*--- ---*/
/*----------------------------------------------------------------*/
/* Do a client request. These are macros rather than a functions so
as to avoid having an extra frame in stack traces.
NB: these duplicate definitions in hg_intercepts.c. But here, we
have to make do with weaker typing (no definition of Word etc) and
no assertions, whereas in helgrind.h we can use those facilities.
Obviously it's important the two sets of definitions are kept in
sync.
The commented-out asserts should actually hold, but unfortunately
they can't be allowed to be visible here, because that would
require the end-user code to #include <assert.h>.
*/
#define DO_CREQ_v_W(_creqF, _ty1F,_arg1F) \
do { \
long int _arg1; \
/* assert(sizeof(_ty1F) == sizeof(long int)); */ \
_arg1 = (long int)(_arg1F); \
VALGRIND_DO_CLIENT_REQUEST_STMT( \
(_creqF), \
_arg1, 0,0,0,0); \
} while (0)
#define DO_CREQ_W_W(_resF, _dfltF, _creqF, _ty1F,_arg1F) \
do { \
long int _arg1; \
/* assert(sizeof(_ty1F) == sizeof(long int)); */ \
_arg1 = (long int)(_arg1F); \
_qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR( \
(_dfltF), \
(_creqF), \
_arg1, 0,0,0,0); \
_resF = _qzz_res; \
} while (0)
#define DO_CREQ_v_WW(_creqF, _ty1F,_arg1F, _ty2F,_arg2F) \
do { \
long int _arg1, _arg2; \
/* assert(sizeof(_ty1F) == sizeof(long int)); */ \
/* assert(sizeof(_ty2F) == sizeof(long int)); */ \
_arg1 = (long int)(_arg1F); \
_arg2 = (long int)(_arg2F); \
VALGRIND_DO_CLIENT_REQUEST_STMT( \
(_creqF), \
_arg1,_arg2,0,0,0); \
} while (0)
#define DO_CREQ_v_WWW(_creqF, _ty1F,_arg1F, \
_ty2F,_arg2F, _ty3F, _arg3F) \
do { \
long int _arg1, _arg2, _arg3; \
/* assert(sizeof(_ty1F) == sizeof(long int)); */ \
/* assert(sizeof(_ty2F) == sizeof(long int)); */ \
/* assert(sizeof(_ty3F) == sizeof(long int)); */ \
_arg1 = (long int)(_arg1F); \
_arg2 = (long int)(_arg2F); \
_arg3 = (long int)(_arg3F); \
VALGRIND_DO_CLIENT_REQUEST_STMT( \
(_creqF), \
_arg1,_arg2,_arg3,0,0); \
} while (0)
#define DO_CREQ_W_WWW(_resF, _dfltF, _creqF, _ty1F,_arg1F, \
_ty2F,_arg2F, _ty3F, _arg3F) \
do { \
long int _qzz_res; \
long int _arg1, _arg2, _arg3; \
/* assert(sizeof(_ty1F) == sizeof(long int)); */ \
_arg1 = (long int)(_arg1F); \
_arg2 = (long int)(_arg2F); \
_arg3 = (long int)(_arg3F); \
_qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR( \
(_dfltF), \
(_creqF), \
_arg1,_arg2,_arg3,0,0); \
_resF = _qzz_res; \
} while (0)
#define _HG_CLIENTREQ_UNIMP(_qzz_str) \
DO_CREQ_v_W(_VG_USERREQ__HG_CLIENTREQ_UNIMP, \
(char*),(_qzz_str))
/*----------------------------------------------------------------*/
/*--- ---*/
/*--- Helgrind-native requests. These allow access to ---*/
/*--- the same set of annotation primitives that are used ---*/
/*--- to build the POSIX pthread wrappers. ---*/
/*--- ---*/
/*----------------------------------------------------------------*/
/* ----------------------------------------------------------
For describing ordinary mutexes (non-rwlocks). For rwlock
descriptions see ANNOTATE_RWLOCK_* below.
---------------------------------------------------------- */
/* Notify here immediately after mutex creation. _mbRec == 0 for a
non-recursive mutex, 1 for a recursive mutex. */
#define VALGRIND_HG_MUTEX_INIT_POST(_mutex, _mbRec) \
DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST, \
void*,(_mutex), long,(_mbRec))
/* Notify here immediately before mutex acquisition. _isTryLock == 0
for a normal acquisition, 1 for a "try" style acquisition. */
#define VALGRIND_HG_MUTEX_LOCK_PRE(_mutex, _isTryLock) \
DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_ACQUIRE_PRE, \
void*,(_mutex), long,(_isTryLock))
/* Notify here immediately after a successful mutex acquisition. */
#define VALGRIND_HG_MUTEX_LOCK_POST(_mutex) \
DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_ACQUIRE_POST, \
void*,(_mutex))
/* Notify here immediately before a mutex release. */
#define VALGRIND_HG_MUTEX_UNLOCK_PRE(_mutex) \
DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE, \
void*,(_mutex))
/* Notify here immediately after a mutex release. */
#define VALGRIND_HG_MUTEX_UNLOCK_POST(_mutex) \
DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST, \
void*,(_mutex))
/* Notify here immediately before mutex destruction. */
#define VALGRIND_HG_MUTEX_DESTROY_PRE(_mutex) \
DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_DESTROY_PRE, \
void*,(_mutex))
/* ----------------------------------------------------------
For describing semaphores.
---------------------------------------------------------- */
/* Notify here immediately after semaphore creation. */
#define VALGRIND_HG_SEM_INIT_POST(_sem, _value) \
DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_INIT_POST, \
void*, (_sem), unsigned long, (_value))
/* Notify here immediately after a semaphore wait (an acquire-style
operation) */
#define VALGRIND_HG_SEM_WAIT_POST(_sem) \
DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_ACQUIRED, \
void*,(_sem))
/* Notify here immediately before semaphore post (a release-style
operation) */
#define VALGRIND_HG_SEM_POST_PRE(_sem) \
DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_RELEASED, \
void*,(_sem))
/* Notify here immediately before semaphore destruction. */
#define VALGRIND_HG_SEM_DESTROY_PRE(_sem) \
DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE, \
void*, (_sem))
/* ----------------------------------------------------------
For describing barriers.
---------------------------------------------------------- */
/* Notify here immediately before barrier creation. _count is the
capacity. _resizable == 0 means the barrier may not be resized, 1
means it may be. */
#define VALGRIND_HG_BARRIER_INIT_PRE(_bar, _count, _resizable) \
DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_BARRIER_INIT_PRE, \
void*,(_bar), \
unsigned long,(_count), \
unsigned long,(_resizable))
/* Notify here immediately before arrival at a barrier. */
#define VALGRIND_HG_BARRIER_WAIT_PRE(_bar) \
DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_BARRIER_WAIT_PRE, \
void*,(_bar))
/* Notify here immediately before a resize (change of barrier
capacity). If _newcount >= the existing capacity, then there is no
change in the state of any threads waiting at the barrier. If
_newcount < the existing capacity, and >= _newcount threads are
currently waiting at the barrier, then this notification is
considered to also have the effect of telling the checker that all
waiting threads have now moved past the barrier. (I can't think of
any other sane semantics.) */
#define VALGRIND_HG_BARRIER_RESIZE_PRE(_bar, _newcount) \
DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_BARRIER_RESIZE_PRE, \
void*,(_bar), \
unsigned long,(_newcount))
/* Notify here immediately before barrier destruction. */
#define VALGRIND_HG_BARRIER_DESTROY_PRE(_bar) \
DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_BARRIER_DESTROY_PRE, \
void*,(_bar))
/* ----------------------------------------------------------
For describing memory ownership changes.
---------------------------------------------------------- */
/* Clean memory state. This makes Helgrind forget everything it knew
about the specified memory range. Effectively this announces that
the specified memory range now "belongs" to the calling thread, so
that: (1) the calling thread can access it safely without
synchronisation, and (2) all other threads must sync with this one
to access it safely. This is particularly useful for memory
allocators that wish to recycle memory. */
#define VALGRIND_HG_CLEAN_MEMORY(_qzz_start, _qzz_len) \
DO_CREQ_v_WW(VG_USERREQ__HG_CLEAN_MEMORY, \
void*,(_qzz_start), \
unsigned long,(_qzz_len))
/* The same, but for the heap block starting at _qzz_blockstart. This
allows painting when we only know the address of an object, but not
its size, which is sometimes the case in C++ code involving
inheritance, and in which RTTI is not, for whatever reason,
available. Returns the number of bytes painted, which can be zero
for a zero-sized block. Hence, return values >= 0 indicate success
(the block was found), and the value -1 indicates block not
found, and -2 is returned when not running on Helgrind. */
#define VALGRIND_HG_CLEAN_MEMORY_HEAPBLOCK(_qzz_blockstart) \
(__extension__ \
({long int _npainted; \
DO_CREQ_W_W(_npainted, (-2)/*default*/, \
_VG_USERREQ__HG_CLEAN_MEMORY_HEAPBLOCK, \
void*,(_qzz_blockstart)); \
_npainted; \
}))
/* ----------------------------------------------------------
For error control.
---------------------------------------------------------- */
/* Tell H that an address range is not to be "tracked" until further
notice. This puts it in the NOACCESS state, in which case we
ignore all reads and writes to it. Useful for ignoring ranges of
memory where there might be races we don't want to see. If the
memory is subsequently reallocated via malloc/new/stack allocation,
then it is put back in the trackable state. Hence it is safe in
the situation where checking is disabled, the containing area is
deallocated and later reallocated for some other purpose. */
#define VALGRIND_HG_DISABLE_CHECKING(_qzz_start, _qzz_len) \
DO_CREQ_v_WW(_VG_USERREQ__HG_ARANGE_MAKE_UNTRACKED, \
void*,(_qzz_start), \
unsigned long,(_qzz_len))
/* And put it back into the normal "tracked" state, that is, make it
once again subject to the normal race-checking machinery. This
puts it in the same state as new memory allocated by this thread --
that is, basically owned exclusively by this thread. */
#define VALGRIND_HG_ENABLE_CHECKING(_qzz_start, _qzz_len) \
DO_CREQ_v_WW(_VG_USERREQ__HG_ARANGE_MAKE_TRACKED, \
void*,(_qzz_start), \
unsigned long,(_qzz_len))
/* Checks the accessibility bits for addresses [zza..zza+zznbytes-1].
If zzabits array is provided, copy the accessibility bits in zzabits.
Return values:
-2 if not running on helgrind
-1 if any parts of zzabits is not addressable
>= 0 : success.
When success, it returns the nr of addressable bytes found.
So, to check that a whole range is addressable, check
VALGRIND_HG_GET_ABITS(addr,NULL,len) == len
In addition, if you want to examine the addressability of each
byte of the range, you need to provide a non NULL ptr as
second argument, pointing to an array of unsigned char
of length len.
Addressable bytes are indicated with 0xff.
Non-addressable bytes are indicated with 0x00.
*/
#define VALGRIND_HG_GET_ABITS(zza,zzabits,zznbytes) \
(__extension__ \
({long int _res; \
DO_CREQ_W_WWW(_res, (-2)/*default*/, \
_VG_USERREQ__HG_GET_ABITS, \
void*,(zza), void*,(zzabits), \
unsigned long,(zznbytes)); \
_res; \
}))
/* End-user request for Ada applications compiled with GNAT.
Helgrind understands the Ada concept of Ada task dependencies and
terminations. See Ada Reference Manual section 9.3 "Task Dependence
- Termination of Tasks".
However, in some cases, the master of (terminated) tasks completes
only when the application exits. An example of this is dynamically
allocated tasks with an access type defined at Library Level.
By default, the state of such tasks in Helgrind will be 'exited but
join not done yet'. Many tasks in such a state are however causing
Helgrind CPU and memory to increase significantly.
VALGRIND_HG_GNAT_DEPENDENT_MASTER_JOIN can be used to indicate
to Helgrind that a not yet completed master has however already
'seen' the termination of a dependent : this is conceptually the
same as a pthread_join and causes the cleanup of the dependent
as done by Helgrind when a master completes.
This allows to avoid the overhead in helgrind caused by such tasks.
A typical usage for a master to indicate it has done conceptually a join
with a dependent task before the master completes is:
while not Dep_Task'Terminated loop
... do whatever to wait for Dep_Task termination.
end loop;
VALGRIND_HG_GNAT_DEPENDENT_MASTER_JOIN
(Dep_Task'Identity,
Ada.Task_Identification.Current_Task);
Note that VALGRIND_HG_GNAT_DEPENDENT_MASTER_JOIN should be a binding
to a C function built with the below macro. */
#define VALGRIND_HG_GNAT_DEPENDENT_MASTER_JOIN(_qzz_dep, _qzz_master) \
DO_CREQ_v_WW(_VG_USERREQ__HG_GNAT_DEPENDENT_MASTER_JOIN, \
void*,(_qzz_dep), \
void*,(_qzz_master))
/*----------------------------------------------------------------*/
/*--- ---*/
/*--- ThreadSanitizer-compatible requests ---*/
/*--- (mostly unimplemented) ---*/
/*--- ---*/
/*----------------------------------------------------------------*/
/* A quite-broad set of annotations, as used in the ThreadSanitizer
project. This implementation aims to be a (source-level)
compatible implementation of the macros defined in:
http://code.google.com/p/data-race-test/source
/browse/trunk/dynamic_annotations/dynamic_annotations.h
(some of the comments below are taken from the above file)
The implementation here is very incomplete, and intended as a
starting point. Many of the macros are unimplemented. Rather than
allowing unimplemented macros to silently do nothing, they cause an
assertion. Intention is to implement them on demand.
The major use of these macros is to make visible to race detectors,
the behaviour (effects) of user-implemented synchronisation
primitives, that the detectors could not otherwise deduce from the
normal observation of pthread etc calls.
Some of the macros are no-ops in Helgrind. That's because Helgrind
is a pure happens-before detector, whereas ThreadSanitizer uses a
hybrid lockset and happens-before scheme, which requires more
accurate annotations for correct operation.
The macros are listed in the same order as in dynamic_annotations.h
(URL just above).
I should point out that I am less than clear about the intended
semantics of quite a number of them. Comments and clarifications
welcomed!
*/
/* ----------------------------------------------------------------
These four allow description of user-level condition variables,
apparently in the style of POSIX's pthread_cond_t. Currently
unimplemented and will assert.
----------------------------------------------------------------
*/
/* Report that wait on the condition variable at address CV has
succeeded and the lock at address LOCK is now held. CV and LOCK
are completely arbitrary memory addresses which presumably mean
something to the application, but are meaningless to Helgrind. */
#define ANNOTATE_CONDVAR_LOCK_WAIT(cv, lock) \
_HG_CLIENTREQ_UNIMP("ANNOTATE_CONDVAR_LOCK_WAIT")
/* Report that wait on the condition variable at CV has succeeded.
Variant w/o lock. */
#define ANNOTATE_CONDVAR_WAIT(cv) \
_HG_CLIENTREQ_UNIMP("ANNOTATE_CONDVAR_WAIT")
/* Report that we are about to signal on the condition variable at
address CV. */
#define ANNOTATE_CONDVAR_SIGNAL(cv) \
_HG_CLIENTREQ_UNIMP("ANNOTATE_CONDVAR_SIGNAL")
/* Report that we are about to signal_all on the condition variable at
CV. */
#define ANNOTATE_CONDVAR_SIGNAL_ALL(cv) \
_HG_CLIENTREQ_UNIMP("ANNOTATE_CONDVAR_SIGNAL_ALL")
/* ----------------------------------------------------------------
Create completely arbitrary happens-before edges between threads.
If threads T1 .. Tn all do ANNOTATE_HAPPENS_BEFORE(obj) and later
(w.r.t. some notional global clock for the computation) thread Tm
does ANNOTATE_HAPPENS_AFTER(obj), then Helgrind will regard all
memory accesses done by T1 .. Tn before the ..BEFORE.. call as
happening-before all memory accesses done by Tm after the
..AFTER.. call. Hence Helgrind won't complain about races if Tm's
accesses afterwards are to the same locations as accesses before by
any of T1 .. Tn.
OBJ is a machine word (unsigned long, or void*), is completely
arbitrary, and denotes the identity of some synchronisation object
you're modelling.
You must do the _BEFORE call just before the real sync event on the
signaller's side, and _AFTER just after the real sync event on the
waiter's side.
If none of the rest of these macros make sense to you, at least
take the time to understand these two. They form the very essence
of describing arbitrary inter-thread synchronisation events to
Helgrind. You can get a long way just with them alone.
See also, extensive discussion on semantics of this in
https://bugs.kde.org/show_bug.cgi?id=243935
ANNOTATE_HAPPENS_BEFORE_FORGET_ALL(obj) is interim until such time
as bug 243935 is fully resolved. It instructs Helgrind to forget
about any ANNOTATE_HAPPENS_BEFORE calls on the specified object, in
effect putting it back in its original state. Once in that state,
a use of ANNOTATE_HAPPENS_AFTER on it has no effect on the calling
thread.
An implementation may optionally release resources it has
associated with 'obj' when ANNOTATE_HAPPENS_BEFORE_FORGET_ALL(obj)
happens. Users are recommended to use
ANNOTATE_HAPPENS_BEFORE_FORGET_ALL to indicate when a
synchronisation object is no longer needed, so as to avoid
potential indefinite resource leaks.
----------------------------------------------------------------
*/
#define ANNOTATE_HAPPENS_BEFORE(obj) \
DO_CREQ_v_W(_VG_USERREQ__HG_USERSO_SEND_PRE, void*,(obj))
#define ANNOTATE_HAPPENS_AFTER(obj) \
DO_CREQ_v_W(_VG_USERREQ__HG_USERSO_RECV_POST, void*,(obj))
#define ANNOTATE_HAPPENS_BEFORE_FORGET_ALL(obj) \
DO_CREQ_v_W(_VG_USERREQ__HG_USERSO_FORGET_ALL, void*,(obj))
/* ----------------------------------------------------------------
Memory publishing. The TSan sources say:
Report that the bytes in the range [pointer, pointer+size) are about
to be published safely. The race checker will create a happens-before
arc from the call ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size) to
subsequent accesses to this memory.
I'm not sure I understand what this means exactly, nor whether it
is relevant for a pure h-b detector. Leaving unimplemented for
now.
----------------------------------------------------------------
*/
#define ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size) \
_HG_CLIENTREQ_UNIMP("ANNOTATE_PUBLISH_MEMORY_RANGE")
/* DEPRECATED. Don't use it. */
/* #define ANNOTATE_UNPUBLISH_MEMORY_RANGE(pointer, size) */
/* DEPRECATED. Don't use it. */
/* #define ANNOTATE_SWAP_MEMORY_RANGE(pointer, size) */
/* ----------------------------------------------------------------
TSan sources say:
Instruct the tool to create a happens-before arc between
MU->Unlock() and MU->Lock(). This annotation may slow down the
race detector; normally it is used only when it would be
difficult to annotate each of the mutex's critical sections
individually using the annotations above.
If MU is a posix pthread_mutex_t then Helgrind will do this anyway.
In any case, leave as unimp for now. I'm unsure about the intended
behaviour.
----------------------------------------------------------------
*/
#define ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mu) \
_HG_CLIENTREQ_UNIMP("ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX")
/* Deprecated. Use ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX. */
/* #define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mu) */
/* ----------------------------------------------------------------
TSan sources say:
Annotations useful when defining memory allocators, or when
memory that was protected in one way starts to be protected in
another.
Report that a new memory at "address" of size "size" has been
allocated. This might be used when the memory has been retrieved
from a free list and is about to be reused, or when a the locking
discipline for a variable changes.
AFAICS this is the same as VALGRIND_HG_CLEAN_MEMORY.
----------------------------------------------------------------
*/
#define ANNOTATE_NEW_MEMORY(address, size) \
VALGRIND_HG_CLEAN_MEMORY((address), (size))
/* ----------------------------------------------------------------
TSan sources say:
Annotations useful when defining FIFO queues that transfer data
between threads.
All unimplemented. Am not claiming to understand this (yet).
----------------------------------------------------------------
*/
/* Report that the producer-consumer queue object at address PCQ has
been created. The ANNOTATE_PCQ_* annotations should be used only
for FIFO queues. For non-FIFO queues use ANNOTATE_HAPPENS_BEFORE
(for put) and ANNOTATE_HAPPENS_AFTER (for get). */
#define ANNOTATE_PCQ_CREATE(pcq) \
_HG_CLIENTREQ_UNIMP("ANNOTATE_PCQ_CREATE")
/* Report that the queue at address PCQ is about to be destroyed. */
#define ANNOTATE_PCQ_DESTROY(pcq) \
_HG_CLIENTREQ_UNIMP("ANNOTATE_PCQ_DESTROY")
/* Report that we are about to put an element into a FIFO queue at
address PCQ. */
#define ANNOTATE_PCQ_PUT(pcq) \
_HG_CLIENTREQ_UNIMP("ANNOTATE_PCQ_PUT")
/* Report that we've just got an element from a FIFO queue at address
PCQ. */
#define ANNOTATE_PCQ_GET(pcq) \
_HG_CLIENTREQ_UNIMP("ANNOTATE_PCQ_GET")
/* ----------------------------------------------------------------
Annotations that suppress errors. It is usually better to express
the program's synchronization using the other annotations, but
these can be used when all else fails.
Currently these are all unimplemented. I can't think of a simple
way to implement them without at least some performance overhead.
----------------------------------------------------------------
*/
/* Report that we may have a benign race at "pointer", with size
"sizeof(*(pointer))". "pointer" must be a non-void* pointer. Insert at the
point where "pointer" has been allocated, preferably close to the point
where the race happens. See also ANNOTATE_BENIGN_RACE_STATIC.
XXX: what's this actually supposed to do? And what's the type of
DESCRIPTION? When does the annotation stop having an effect?
*/
#define ANNOTATE_BENIGN_RACE(pointer, description) \
_HG_CLIENTREQ_UNIMP("ANNOTATE_BENIGN_RACE")
/* Same as ANNOTATE_BENIGN_RACE(address, description), but applies to
the memory range [address, address+size). */
#define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
VALGRIND_HG_DISABLE_CHECKING(address, size)
/* Request the analysis tool to ignore all reads in the current thread
until ANNOTATE_IGNORE_READS_END is called. Useful to ignore
intentional racey reads, while still checking other reads and all
writes. */
#define ANNOTATE_IGNORE_READS_BEGIN() \
_HG_CLIENTREQ_UNIMP("ANNOTATE_IGNORE_READS_BEGIN")
/* Stop ignoring reads. */
#define ANNOTATE_IGNORE_READS_END() \
_HG_CLIENTREQ_UNIMP("ANNOTATE_IGNORE_READS_END")
/* Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes. */
#define ANNOTATE_IGNORE_WRITES_BEGIN() \
_HG_CLIENTREQ_UNIMP("ANNOTATE_IGNORE_WRITES_BEGIN")
/* Stop ignoring writes. */
#define ANNOTATE_IGNORE_WRITES_END() \
_HG_CLIENTREQ_UNIMP("ANNOTATE_IGNORE_WRITES_END")
/* Start ignoring all memory accesses (reads and writes). */
#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
do { \
ANNOTATE_IGNORE_READS_BEGIN(); \
ANNOTATE_IGNORE_WRITES_BEGIN(); \
} while (0)
/* Stop ignoring all memory accesses. */
#define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
do { \
ANNOTATE_IGNORE_WRITES_END(); \
ANNOTATE_IGNORE_READS_END(); \
} while (0)
/* ----------------------------------------------------------------
Annotations useful for debugging.
Again, so for unimplemented, partly for performance reasons.
----------------------------------------------------------------
*/
/* Request to trace every access to ADDRESS. */
#define ANNOTATE_TRACE_MEMORY(address) \
_HG_CLIENTREQ_UNIMP("ANNOTATE_TRACE_MEMORY")
/* Report the current thread name to a race detector. */
#define ANNOTATE_THREAD_NAME(name) \
_HG_CLIENTREQ_UNIMP("ANNOTATE_THREAD_NAME")
/* ----------------------------------------------------------------
Annotations for describing behaviour of user-implemented lock
primitives. In all cases, the LOCK argument is a completely
arbitrary machine word (unsigned long, or void*) and can be any
value which gives a unique identity to the lock objects being
modelled.
We just pretend they're ordinary posix rwlocks. That'll probably
give some rather confusing wording in error messages, claiming that
the arbitrary LOCK values are pthread_rwlock_t*'s, when in fact
they are not. Ah well.
----------------------------------------------------------------
*/
/* Report that a lock has just been created at address LOCK. */
#define ANNOTATE_RWLOCK_CREATE(lock) \
DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_INIT_POST, \
void*,(lock))
/* Report that the lock at address LOCK is about to be destroyed. */
#define ANNOTATE_RWLOCK_DESTROY(lock) \
DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_DESTROY_PRE, \
void*,(lock))
/* Report that the lock at address LOCK has just been acquired.
is_w=1 for writer lock, is_w=0 for reader lock. */
#define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_ACQUIRED, \
void*,(lock), unsigned long,(is_w))
/* Report that the lock at address LOCK is about to be released. */
#define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_RELEASED, \
void*,(lock)) /* is_w is ignored */
/* -------------------------------------------------------------
Annotations useful when implementing barriers. They are not
normally needed by modules that merely use barriers.
The "barrier" argument is a pointer to the barrier object.
----------------------------------------------------------------
*/
/* Report that the "barrier" has been initialized with initial
"count". If 'reinitialization_allowed' is true, initialization is
allowed to happen multiple times w/o calling barrier_destroy() */
#define ANNOTATE_BARRIER_INIT(barrier, count, reinitialization_allowed) \
_HG_CLIENTREQ_UNIMP("ANNOTATE_BARRIER_INIT")
/* Report that we are about to enter barrier_wait("barrier"). */
#define ANNOTATE_BARRIER_WAIT_BEFORE(barrier) \
_HG_CLIENTREQ_UNIMP("ANNOTATE_BARRIER_DESTROY")
/* Report that we just exited barrier_wait("barrier"). */
#define ANNOTATE_BARRIER_WAIT_AFTER(barrier) \
_HG_CLIENTREQ_UNIMP("ANNOTATE_BARRIER_DESTROY")
/* Report that the "barrier" has been destroyed. */
#define ANNOTATE_BARRIER_DESTROY(barrier) \
_HG_CLIENTREQ_UNIMP("ANNOTATE_BARRIER_DESTROY")
/* ----------------------------------------------------------------
Annotations useful for testing race detectors.
----------------------------------------------------------------
*/
/* Report that we expect a race on the variable at ADDRESS. Use only
in unit tests for a race detector. */
#define ANNOTATE_EXPECT_RACE(address, description) \
_HG_CLIENTREQ_UNIMP("ANNOTATE_EXPECT_RACE")
/* A no-op. Insert where you like to test the interceptors. */
#define ANNOTATE_NO_OP(arg) \
_HG_CLIENTREQ_UNIMP("ANNOTATE_NO_OP")
/* Force the race detector to flush its state. The actual effect depends on
* the implementation of the detector. */
#define ANNOTATE_FLUSH_STATE() \
_HG_CLIENTREQ_UNIMP("ANNOTATE_FLUSH_STATE")
#endif /* __HELGRIND_H */

310
third_party/valgrind/memcheck.h vendored Normal file
View File

@@ -0,0 +1,310 @@
/*
----------------------------------------------------------------
Notice that the following BSD-style license applies to this one
file (memcheck.h) only. The rest of Valgrind is licensed under the
terms of the GNU General Public License, version 2, unless
otherwise indicated. See the COPYING file in the source
distribution for details.
----------------------------------------------------------------
This file is part of MemCheck, a heavyweight Valgrind tool for
detecting memory errors.
Copyright (C) 2000-2017 Julian Seward. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------
Notice that the above BSD-style license applies to this one file
(memcheck.h) only. The entire rest of Valgrind is licensed under
the terms of the GNU General Public License, version 2. See the
COPYING file in the source distribution for details.
----------------------------------------------------------------
*/
#ifndef __MEMCHECK_H
#define __MEMCHECK_H
/* This file is for inclusion into client (your!) code.
You can use these macros to manipulate and query memory permissions
inside your own programs.
See comment near the top of valgrind.h on how to use them.
*/
#include "valgrind.h"
/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
This enum comprises an ABI exported by Valgrind to programs
which use client requests. DO NOT CHANGE THE ORDER OF THESE
ENTRIES, NOR DELETE ANY -- add new ones at the end. */
typedef
enum {
VG_USERREQ__MAKE_MEM_NOACCESS = VG_USERREQ_TOOL_BASE('M','C'),
VG_USERREQ__MAKE_MEM_UNDEFINED,
VG_USERREQ__MAKE_MEM_DEFINED,
VG_USERREQ__DISCARD,
VG_USERREQ__CHECK_MEM_IS_ADDRESSABLE,
VG_USERREQ__CHECK_MEM_IS_DEFINED,
VG_USERREQ__DO_LEAK_CHECK,
VG_USERREQ__COUNT_LEAKS,
VG_USERREQ__GET_VBITS,
VG_USERREQ__SET_VBITS,
VG_USERREQ__CREATE_BLOCK,
VG_USERREQ__MAKE_MEM_DEFINED_IF_ADDRESSABLE,
/* Not next to VG_USERREQ__COUNT_LEAKS because it was added later. */
VG_USERREQ__COUNT_LEAK_BLOCKS,
VG_USERREQ__ENABLE_ADDR_ERROR_REPORTING_IN_RANGE,
VG_USERREQ__DISABLE_ADDR_ERROR_REPORTING_IN_RANGE,
/* This is just for memcheck's internal use - don't use it */
_VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR
= VG_USERREQ_TOOL_BASE('M','C') + 256,
_VG_USERREQ__MEMCHECK_VERIFY_ALIGNMENT
} Vg_MemCheckClientRequest;
/* Client-code macros to manipulate the state of memory. */
/* Mark memory at _qzz_addr as unaddressable for _qzz_len bytes. */
#define VALGRIND_MAKE_MEM_NOACCESS(_qzz_addr,_qzz_len) \
VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
VG_USERREQ__MAKE_MEM_NOACCESS, \
(_qzz_addr), (_qzz_len), 0, 0, 0)
/* Similarly, mark memory at _qzz_addr as addressable but undefined
for _qzz_len bytes. */
#define VALGRIND_MAKE_MEM_UNDEFINED(_qzz_addr,_qzz_len) \
VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
VG_USERREQ__MAKE_MEM_UNDEFINED, \
(_qzz_addr), (_qzz_len), 0, 0, 0)
/* Similarly, mark memory at _qzz_addr as addressable and defined
for _qzz_len bytes. */
#define VALGRIND_MAKE_MEM_DEFINED(_qzz_addr,_qzz_len) \
VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
VG_USERREQ__MAKE_MEM_DEFINED, \
(_qzz_addr), (_qzz_len), 0, 0, 0)
/* Similar to VALGRIND_MAKE_MEM_DEFINED except that addressability is
not altered: bytes which are addressable are marked as defined,
but those which are not addressable are left unchanged. */
#define VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(_qzz_addr,_qzz_len) \
VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
VG_USERREQ__MAKE_MEM_DEFINED_IF_ADDRESSABLE, \
(_qzz_addr), (_qzz_len), 0, 0, 0)
/* Create a block-description handle. The description is an ascii
string which is included in any messages pertaining to addresses
within the specified memory range. Has no other effect on the
properties of the memory range. */
#define VALGRIND_CREATE_BLOCK(_qzz_addr,_qzz_len, _qzz_desc) \
VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
VG_USERREQ__CREATE_BLOCK, \
(_qzz_addr), (_qzz_len), (_qzz_desc), \
0, 0)
/* Discard a block-description-handle. Returns 1 for an
invalid handle, 0 for a valid handle. */
#define VALGRIND_DISCARD(_qzz_blkindex) \
VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
VG_USERREQ__DISCARD, \
0, (_qzz_blkindex), 0, 0, 0)
/* Client-code macros to check the state of memory. */
/* Check that memory at _qzz_addr is addressable for _qzz_len bytes.
If suitable addressibility is not established, Valgrind prints an
error message and returns the address of the first offending byte.
Otherwise it returns zero. */
#define VALGRIND_CHECK_MEM_IS_ADDRESSABLE(_qzz_addr,_qzz_len) \
VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
VG_USERREQ__CHECK_MEM_IS_ADDRESSABLE, \
(_qzz_addr), (_qzz_len), 0, 0, 0)
/* Check that memory at _qzz_addr is addressable and defined for
_qzz_len bytes. If suitable addressibility and definedness are not
established, Valgrind prints an error message and returns the
address of the first offending byte. Otherwise it returns zero. */
#define VALGRIND_CHECK_MEM_IS_DEFINED(_qzz_addr,_qzz_len) \
VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
VG_USERREQ__CHECK_MEM_IS_DEFINED, \
(_qzz_addr), (_qzz_len), 0, 0, 0)
/* Use this macro to force the definedness and addressibility of an
lvalue to be checked. If suitable addressibility and definedness
are not established, Valgrind prints an error message and returns
the address of the first offending byte. Otherwise it returns
zero. */
#define VALGRIND_CHECK_VALUE_IS_DEFINED(__lvalue) \
VALGRIND_CHECK_MEM_IS_DEFINED( \
(volatile unsigned char *)&(__lvalue), \
(unsigned long)(sizeof (__lvalue)))
/* Do a full memory leak check (like --leak-check=full) mid-execution. */
#define VALGRIND_DO_LEAK_CHECK \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DO_LEAK_CHECK, \
0, 0, 0, 0, 0)
/* Same as VALGRIND_DO_LEAK_CHECK but only showing the entries for
which there was an increase in leaked bytes or leaked nr of blocks
since the previous leak search. */
#define VALGRIND_DO_ADDED_LEAK_CHECK \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DO_LEAK_CHECK, \
0, 1, 0, 0, 0)
/* Same as VALGRIND_DO_ADDED_LEAK_CHECK but showing entries with
increased or decreased leaked bytes/blocks since previous leak
search. */
#define VALGRIND_DO_CHANGED_LEAK_CHECK \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DO_LEAK_CHECK, \
0, 2, 0, 0, 0)
/* Same as VALGRIND_DO_LEAK_CHECK but only showing new entries
i.e. loss records that were not there in the previous leak
search. */
#define VALGRIND_DO_NEW_LEAK_CHECK \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DO_LEAK_CHECK, \
0, 3, 0, 0, 0)
/* Do a summary memory leak check (like --leak-check=summary) mid-execution. */
#define VALGRIND_DO_QUICK_LEAK_CHECK \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DO_LEAK_CHECK, \
1, 0, 0, 0, 0)
/* Return number of leaked, dubious, reachable and suppressed bytes found by
all previous leak checks. They must be lvalues. */
#define VALGRIND_COUNT_LEAKS(leaked, dubious, reachable, suppressed) \
/* For safety on 64-bit platforms we assign the results to private
unsigned long variables, then assign these to the lvalues the user
specified, which works no matter what type 'leaked', 'dubious', etc
are. We also initialise '_qzz_leaked', etc because
VG_USERREQ__COUNT_LEAKS doesn't mark the values returned as
defined. */ \
{ \
unsigned long _qzz_leaked = 0, _qzz_dubious = 0; \
unsigned long _qzz_reachable = 0, _qzz_suppressed = 0; \
VALGRIND_DO_CLIENT_REQUEST_STMT( \
VG_USERREQ__COUNT_LEAKS, \
&_qzz_leaked, &_qzz_dubious, \
&_qzz_reachable, &_qzz_suppressed, 0); \
leaked = _qzz_leaked; \
dubious = _qzz_dubious; \
reachable = _qzz_reachable; \
suppressed = _qzz_suppressed; \
}
/* Return number of leaked, dubious, reachable and suppressed bytes found by
all previous leak checks. They must be lvalues. */
#define VALGRIND_COUNT_LEAK_BLOCKS(leaked, dubious, reachable, suppressed) \
/* For safety on 64-bit platforms we assign the results to private
unsigned long variables, then assign these to the lvalues the user
specified, which works no matter what type 'leaked', 'dubious', etc
are. We also initialise '_qzz_leaked', etc because
VG_USERREQ__COUNT_LEAKS doesn't mark the values returned as
defined. */ \
{ \
unsigned long _qzz_leaked = 0, _qzz_dubious = 0; \
unsigned long _qzz_reachable = 0, _qzz_suppressed = 0; \
VALGRIND_DO_CLIENT_REQUEST_STMT( \
VG_USERREQ__COUNT_LEAK_BLOCKS, \
&_qzz_leaked, &_qzz_dubious, \
&_qzz_reachable, &_qzz_suppressed, 0); \
leaked = _qzz_leaked; \
dubious = _qzz_dubious; \
reachable = _qzz_reachable; \
suppressed = _qzz_suppressed; \
}
/* Get the validity data for addresses [zza..zza+zznbytes-1] and copy it
into the provided zzvbits array. Return values:
0 if not running on valgrind
1 success
2 [previously indicated unaligned arrays; these are now allowed]
3 if any parts of zzsrc/zzvbits are not addressable.
The metadata is not copied in cases 0, 2 or 3 so it should be
impossible to segfault your system by using this call.
*/
#define VALGRIND_GET_VBITS(zza,zzvbits,zznbytes) \
(unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
VG_USERREQ__GET_VBITS, \
(const char*)(zza), \
(char*)(zzvbits), \
(zznbytes), 0, 0)
/* Set the validity data for addresses [zza..zza+zznbytes-1], copying it
from the provided zzvbits array. Return values:
0 if not running on valgrind
1 success
2 [previously indicated unaligned arrays; these are now allowed]
3 if any parts of zza/zzvbits are not addressable.
The metadata is not copied in cases 0, 2 or 3 so it should be
impossible to segfault your system by using this call.
*/
#define VALGRIND_SET_VBITS(zza,zzvbits,zznbytes) \
(unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
VG_USERREQ__SET_VBITS, \
(const char*)(zza), \
(const char*)(zzvbits), \
(zznbytes), 0, 0 )
/* Disable and re-enable reporting of addressing errors in the
specified address range. */
#define VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(_qzz_addr,_qzz_len) \
VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
VG_USERREQ__DISABLE_ADDR_ERROR_REPORTING_IN_RANGE, \
(_qzz_addr), (_qzz_len), 0, 0, 0)
#define VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(_qzz_addr,_qzz_len) \
VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
VG_USERREQ__ENABLE_ADDR_ERROR_REPORTING_IN_RANGE, \
(_qzz_addr), (_qzz_len), 0, 0, 0)
#endif

7165
third_party/valgrind/valgrind.h vendored Normal file

File diff suppressed because it is too large Load Diff