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
AnnotateRWLockCreate(const char *,int,const volatile void *)45 void AnnotateRWLockCreate(const char *, int,
46 const volatile void *){}
AnnotateRWLockDestroy(const char *,int,const volatile void *)47 void AnnotateRWLockDestroy(const char *, int,
48 const volatile void *){}
AnnotateRWLockAcquired(const char *,int,const volatile void *,long)49 void AnnotateRWLockAcquired(const char *, int,
50 const volatile void *, long){}
AnnotateRWLockReleased(const char *,int,const volatile void *,long)51 void AnnotateRWLockReleased(const char *, int,
52 const volatile void *, long){}
AnnotateBenignRace(const char *,int,const volatile void *,const char *)53 void AnnotateBenignRace(const char *, int,
54 const volatile void *,
55 const char *){}
AnnotateBenignRaceSized(const char *,int,const volatile void *,size_t,const char *)56 void AnnotateBenignRaceSized(const char *, int,
57 const volatile void *,
58 size_t,
59 const char *) {}
AnnotateThreadName(const char *,int,const char *)60 void AnnotateThreadName(const char *, int,
61 const char *){}
AnnotateIgnoreReadsBegin(const char *,int)62 void AnnotateIgnoreReadsBegin(const char *, int){}
AnnotateIgnoreReadsEnd(const char *,int)63 void AnnotateIgnoreReadsEnd(const char *, int){}
AnnotateIgnoreWritesBegin(const char *,int)64 void AnnotateIgnoreWritesBegin(const char *, int){}
AnnotateIgnoreWritesEnd(const char *,int)65 void AnnotateIgnoreWritesEnd(const char *, int){}
AnnotateEnableRaceDetection(const char *,int,int)66 void AnnotateEnableRaceDetection(const char *, int, int){}
AnnotateMemoryIsInitialized(const char *,int,const volatile void * mem,size_t size)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
AnnotateMemoryIsUninitialized(const char *,int,const volatile void * mem,size_t size)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
GetRunningOnValgrind(void)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 */
RunningOnValgrind(void)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 */
ValgrindSlowdown(void)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