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 |
42 | extern "C" { |
43 | #endif |
44 | |
45 | void AnnotateRWLockCreate(const char *, int, |
46 | const volatile void *){} |
47 | void AnnotateRWLockDestroy(const char *, int, |
48 | const volatile void *){} |
49 | void AnnotateRWLockAcquired(const char *, int, |
50 | const volatile void *, long){} |
51 | void AnnotateRWLockReleased(const char *, int, |
52 | const volatile void *, long){} |
53 | void AnnotateBenignRace(const char *, int, |
54 | const volatile void *, |
55 | const char *){} |
56 | void AnnotateBenignRaceSized(const char *, int, |
57 | const volatile void *, |
58 | size_t, |
59 | const char *) {} |
60 | void AnnotateThreadName(const char *, int, |
61 | const char *){} |
62 | void AnnotateIgnoreReadsBegin(const char *, int){} |
63 | void AnnotateIgnoreReadsEnd(const char *, int){} |
64 | void AnnotateIgnoreWritesBegin(const char *, int){} |
65 | void AnnotateIgnoreWritesEnd(const char *, int){} |
66 | void AnnotateEnableRaceDetection(const char *, int, int){} |
67 | void 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 | |
77 | void 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 | |
87 | static 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 */ |
99 | int 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 */ |
111 | double 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 | |