iai_callgrind/client_requests/drd.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
// 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.
//
// ----------------------------------------------------------------
//
// We're using a lot of the original documentation from the `drd.h` header file with some
// small adjustments, so above is the original license from `drd.h` file.
//
// This file is distributed under the same License as the rest of `iai-callgrind`.
//
// ----------------------------------------------------------------
//
//! All public client requests from the `drd.h` header file
//!
//! The client requests which do nothing or are not implemented (as of valgrind version 3.22) are
//! not available.
//!
//! See also [DRD Client
//! Requests](https://valgrind.org/docs/manual/drd-manual.html#drd-manual.clientreqs)
use std::ffi::CStr;
use super::arch::imp::valgrind_do_client_request_expr;
use super::arch::valgrind_do_client_request_stmt;
use super::{bindings, fatal_error, helgrind};
/// Obtain the thread ID assigned by Valgrind's core
///
/// Valgrind's thread ID's start at one and are recycled in case a thread stops.
#[inline(always)]
pub fn get_valgrind_threadid() -> usize {
do_client_request!(
"drd::get_valgrind_threadid",
0,
bindings::IC_DRDClientRequest::IC_DRD_GET_VALGRIND_THREAD_ID,
0,
0,
0,
0,
0
)
}
/// Obtain the thread ID assigned by DRD
///
/// These are the thread ID's reported by DRD in data race reports and in trace messages. DRD's
/// thread ID's start at one and are never recycled.
#[inline(always)]
pub fn get_drd_threadid() -> usize {
do_client_request!(
"drd::get_drd_threadid",
0,
bindings::IC_DRDClientRequest::IC_DRD_GET_DRD_THREAD_ID,
0,
0,
0,
0,
0
)
}
/// Tell DRD not to complain about data races for the specified variable
///
/// Some applications contain intentional races. There exist e.g. applications where the same value
/// is assigned to a shared variable from two different threads. It may be more convenient to
/// suppress such races than to solve these. This client request allows one to suppress such races.
#[inline(always)]
pub fn ignore_var<T>(var: &T) {
do_client_request!(
"drd::ignore_var",
bindings::IC_DRDClientRequest::IC_DRD_START_SUPPRESSION,
var as *const T as usize,
core::mem::size_of::<T>(),
0,
0,
0
);
}
/// Tell DRD to no longer ignore data races for the specified variable that was suppressed via
/// [`ignore_var`]
#[inline(always)]
pub fn stop_ignoring_var<T>(var: &T) {
do_client_request!(
"drd::stop_ignoring_var",
bindings::IC_DRDClientRequest::IC_DRD_FINISH_SUPPRESSION,
var as *const T as usize,
core::mem::size_of::<T>(),
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.
///
/// When DRD reports a data race on a specified variable, and it's not immediately clear which
/// source code statements triggered the conflicting accesses, it can be very helpful to trace all
/// activity on the offending memory location.
#[inline(always)]
pub fn trace_var<T>(var: &T) {
do_client_request!(
"drd::trace_var",
bindings::IC_DRDClientRequest::IC_DRD_START_TRACE_ADDR,
var as *const T as usize,
core::mem::size_of::<T>(),
0,
0,
0
);
}
/// Tell DRD to stop tracing memory accesses for the specified variable
#[inline(always)]
pub fn stop_tracing_var<T>(var: &T) {
do_client_request!(
"drd::stop_tracing_var",
bindings::IC_DRDClientRequest::IC_DRD_STOP_TRACE_ADDR,
var as *const T as usize,
core::mem::size_of::<T>(),
0,
0,
0
);
}
/// Create completely arbitrary happens-before edges between threads
///
/// See [`super::helgrind::annotate_happens_before`]
#[inline(always)]
pub fn annotate_happens_before(obj: *const ()) {
helgrind::annotate_happens_before(obj);
}
/// See [`super::helgrind::annotate_happens_before`]
#[inline(always)]
pub fn annotate_happens_after(obj: *const ()) {
helgrind::annotate_happens_after(obj);
}
/// Report that a lock has just been created at address `lock`
///
/// See [`super::helgrind::annotate_rwlock_create`]
#[inline(always)]
pub fn annotate_rwlock_create(lock: *const ()) {
helgrind::annotate_rwlock_create(lock);
}
/// Report that the lock at address `lock` is about to be destroyed
///
/// See [`super::helgrind::annotate_rwlock_create`]
#[inline(always)]
pub fn annotate_rwlock_destroy(lock: *const ()) {
helgrind::annotate_rwlock_destroy(lock);
}
/// Report that the lock at address `lock` has just been acquired
///
/// See also [`super::helgrind::annotate_rwlock_create`]
#[inline(always)]
pub fn annotate_rwlock_acquired(lock: *const (), is_writer_lock: bool) {
helgrind::annotate_rwlock_acquired(lock, is_writer_lock);
}
/// Report that the lock at address `lock` is about to be released
///
/// See also [`super::helgrind::annotate_rwlock_create`]
#[inline(always)]
pub fn annotate_rwlock_released(lock: *const (), is_writer_lock: bool) {
helgrind::annotate_rwlock_released(lock, is_writer_lock);
}
/// Tell DRD that data races at the specified address are expected and must not be reported
///
/// Any races detected on the specified variable are benign and hence should not be reported.
#[inline(always)]
pub fn annotate_benign_race<T>(addr: &T) {
do_client_request!(
"drd::annotate_benign_race",
bindings::IC_DRDClientRequest::IC_DRD_START_SUPPRESSION,
addr as *const T as usize,
core::mem::size_of::<T>(),
0,
0,
0
);
}
/// Same as [`annotate_benign_race`], but applies to the memory range [addr, addr + size).
///
/// Any races detected on the specified variable are benign and hence should not be reported.
#[inline(always)]
pub fn annotate_benign_race_sized<T>(addr: &T, size: usize) {
do_client_request!(
"drd::annotate_benign_race_sized",
bindings::IC_DRDClientRequest::IC_DRD_START_SUPPRESSION,
addr as *const T as usize,
size,
0,
0,
0
);
}
/// Tell DRD to ignore all reads performed by the current thread
#[inline(always)]
pub fn annotate_ignore_reads_begin() {
do_client_request!(
"drd::annotate_ignore_reads_begin",
bindings::IC_DRDClientRequest::IC_DRD_RECORD_LOADS,
0,
0,
0,
0,
0
);
}
/// Tell DRD to no longer ignore the reads performed by the current thread.
#[inline(always)]
pub fn annotate_ignore_reads_end() {
do_client_request!(
"drd::annotate_ignore_reads_end",
bindings::IC_DRDClientRequest::IC_DRD_RECORD_LOADS,
1,
0,
0,
0,
0
);
}
/// Tell DRD to ignore all writes performed by the current thread.
#[inline(always)]
pub fn annotate_ignore_writes_begin() {
do_client_request!(
"drd::annotate_ignore_writes_begin",
bindings::IC_DRDClientRequest::IC_DRD_RECORD_STORES,
0,
0,
0,
0,
0
);
}
/// Tell DRD to no longer ignore the writes performed by the current thread.
#[inline(always)]
pub fn annotate_ignore_writes_end() {
do_client_request!(
"drd::annotate_ignore_writes_end",
bindings::IC_DRDClientRequest::IC_DRD_RECORD_STORES,
1,
0,
0,
0,
0
);
}
/// Tell DRD to ignore all memory accesses performed by the current thread.
#[inline(always)]
pub fn annotate_ignore_reads_and_writes_begin() {
annotate_ignore_reads_begin();
annotate_ignore_writes_begin();
}
/// Tell DRD to no longer ignore the memory accesses performed by the current thread.
#[inline(always)]
pub fn annotate_ignore_reads_and_writes_end() {
annotate_ignore_reads_end();
annotate_ignore_writes_end();
}
/// Tell DRD that size bytes starting at addr has been allocated by a custom memory allocator
#[inline(always)]
pub fn annotate_new_memory(addr: *const (), size: usize) {
do_client_request!(
"drd::annotate_new_memory",
bindings::IC_DRDClientRequest::IC_DRD_CLEAN_MEMORY,
addr as usize,
size,
0,
0,
0
);
}
/// Ask DRD to report every access to the specified address
///
/// Trace all load and store activity that touches at least the single byte at the address `addr`.
#[inline(always)]
pub fn annotate_trace_memory(addr: *const ()) {
do_client_request!(
"drd::annotate_trace_memory",
bindings::IC_DRDClientRequest::IC_DRD_START_TRACE_ADDR,
addr as usize,
core::mem::size_of::<cty::c_char>(),
0,
0,
0
);
}
/// Tell DRD to assign the specified name to the current thread.
///
/// This name will be used in error messages printed by DRD.
#[inline(always)]
pub fn annotate_thread_name<T>(name: T)
where
T: AsRef<CStr>,
{
do_client_request!(
"drd::annotate_thread_name",
bindings::IC_DRDClientRequest::IC_DRD_SET_THREAD_NAME,
name.as_ref().as_ptr() as usize,
0,
0,
0,
0
);
}