1// Copyright 2017 The Abseil Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include <stdlib.h>
16#include <string.h>
17
18#include "absl/base/dynamic_annotations.h"
19
20#ifndef __has_feature
21#define __has_feature(x) 0
22#endif
23
24/* Compiler-based ThreadSanitizer defines
25 DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL = 1
26 and provides its own definitions of the functions. */
27
28#ifndef DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL
29# define DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL 0
30#endif
31
32/* Each function is empty and called (via a macro) only in debug mode.
33 The arguments are captured by dynamic tools at runtime. */
34
35#if DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 && !defined(__native_client__)
36
37#if __has_feature(memory_sanitizer)
38#include <sanitizer/msan_interface.h>
39#endif
40
41#ifdef __cplusplus
42extern "C" {
43#endif
44
45void AnnotateRWLockCreate(const char *, int,
46 const volatile void *){}
47void AnnotateRWLockDestroy(const char *, int,
48 const volatile void *){}
49void AnnotateRWLockAcquired(const char *, int,
50 const volatile void *, long){}
51void AnnotateRWLockReleased(const char *, int,
52 const volatile void *, long){}
53void AnnotateBenignRace(const char *, int,
54 const volatile void *,
55 const char *){}
56void AnnotateBenignRaceSized(const char *, int,
57 const volatile void *,
58 size_t,
59 const char *) {}
60void AnnotateThreadName(const char *, int,
61 const char *){}
62void AnnotateIgnoreReadsBegin(const char *, int){}
63void AnnotateIgnoreReadsEnd(const char *, int){}
64void AnnotateIgnoreWritesBegin(const char *, int){}
65void AnnotateIgnoreWritesEnd(const char *, int){}
66void AnnotateEnableRaceDetection(const char *, int, int){}
67void AnnotateMemoryIsInitialized(const char *, int,
68 const volatile void *mem, size_t size) {
69#if __has_feature(memory_sanitizer)
70 __msan_unpoison(mem, size);
71#else
72 (void)mem;
73 (void)size;
74#endif
75}
76
77void AnnotateMemoryIsUninitialized(const char *, int,
78 const volatile void *mem, size_t size) {
79#if __has_feature(memory_sanitizer)
80 __msan_allocated_memory(mem, size);
81#else
82 (void)mem;
83 (void)size;
84#endif
85}
86
87static int GetRunningOnValgrind(void) {
88#ifdef RUNNING_ON_VALGRIND
89 if (RUNNING_ON_VALGRIND) return 1;
90#endif
91 char *running_on_valgrind_str = getenv("RUNNING_ON_VALGRIND");
92 if (running_on_valgrind_str) {
93 return strcmp(running_on_valgrind_str, "0") != 0;
94 }
95 return 0;
96}
97
98/* See the comments in dynamic_annotations.h */
99int RunningOnValgrind(void) {
100 static volatile int running_on_valgrind = -1;
101 int local_running_on_valgrind = running_on_valgrind;
102 /* C doesn't have thread-safe initialization of statics, and we
103 don't want to depend on pthread_once here, so hack it. */
104 ANNOTATE_BENIGN_RACE(&running_on_valgrind, "safe hack");
105 if (local_running_on_valgrind == -1)
106 running_on_valgrind = local_running_on_valgrind = GetRunningOnValgrind();
107 return local_running_on_valgrind;
108}
109
110/* See the comments in dynamic_annotations.h */
111double ValgrindSlowdown(void) {
112 /* Same initialization hack as in RunningOnValgrind(). */
113 static volatile double slowdown = 0.0;
114 double local_slowdown = slowdown;
115 ANNOTATE_BENIGN_RACE(&slowdown, "safe hack");
116 if (RunningOnValgrind() == 0) {
117 return 1.0;
118 }
119 if (local_slowdown == 0.0) {
120 char *env = getenv("VALGRIND_SLOWDOWN");
121 slowdown = local_slowdown = env ? atof(env) : 50.0;
122 }
123 return local_slowdown;
124}
125
126#ifdef __cplusplus
127} // extern "C"
128#endif
129#endif /* DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 */
130