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
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:
@@ -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()
|
||||||
|
@@ -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);
|
||||||
|
14
Internal.h
14
Internal.h
@@ -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
98
third_party/valgrind/cachegrind.h
vendored
Normal 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
129
third_party/valgrind/callgrind.h
vendored
Normal 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
86
third_party/valgrind/dhat.h
vendored
Normal 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
571
third_party/valgrind/drd.h
vendored
Normal 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
830
third_party/valgrind/helgrind.h
vendored
Normal 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
310
third_party/valgrind/memcheck.h
vendored
Normal 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
7165
third_party/valgrind/valgrind.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user