1 // This file is used from other tests.
2 // RUN: true
3 
4 #include <dlfcn.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 
8 struct MyObject;
9 typedef MyObject *MyObjectRef;
10 extern "C" {
11   void InitializeLibrary();
12   MyObject *ObjectCreate();
13   long ObjectRead(MyObject *);
14   void ObjectWrite(MyObject *, long);
15   void ObjectWriteAnother(MyObject *, long);
16 }
17 
18 struct MyObject {
19   long _val;
20   long _another;
21 };
22 
23 #if defined(USE_TSAN_CALLBACKS)
24 static void *tag;
25 void *(*callback_register_tag)(const char *object_type);
26 void *(*callback_assign_tag)(void *addr, void *tag);
27 void (*callback_read)(void *addr, void *caller_pc, void *tag);
28 void (*callback_write)(void *addr, void *caller_pc, void *tag);
29 #endif
30 
InitializeLibrary()31 void InitializeLibrary() {
32 #if defined(USE_TSAN_CALLBACKS)
33   callback_register_tag = (decltype(callback_register_tag))dlsym(RTLD_DEFAULT, "__tsan_external_register_tag");
34   callback_assign_tag = (decltype(callback_assign_tag))dlsym(RTLD_DEFAULT, "__tsan_external_assign_tag");
35   callback_read = (decltype(callback_read))dlsym(RTLD_DEFAULT, "__tsan_external_read");
36   callback_write = (decltype(callback_write))dlsym(RTLD_DEFAULT, "__tsan_external_write");
37   tag = callback_register_tag("MyLibrary::MyObject");
38 #endif
39 }
40 
ObjectCreate()41 MyObject *ObjectCreate() {
42   MyObject *ref = (MyObject *)malloc(sizeof(MyObject));
43 #if defined(USE_TSAN_CALLBACKS)
44   callback_assign_tag(ref, tag);
45 #endif
46   return ref;
47 }
48 
ObjectRead(MyObject * ref)49 long ObjectRead(MyObject *ref) {
50 #if defined(USE_TSAN_CALLBACKS)
51   callback_read(ref, __builtin_return_address(0), tag);
52 #endif
53   return ref->_val;
54 }
55 
ObjectWrite(MyObject * ref,long val)56 void ObjectWrite(MyObject *ref, long val) {
57 #if defined(USE_TSAN_CALLBACKS)
58   callback_write(ref, __builtin_return_address(0), tag);
59 #endif
60   ref->_val = val;
61 }
62 
ObjectWriteAnother(MyObject * ref,long val)63 void ObjectWriteAnother(MyObject *ref, long val) {
64 #if defined(USE_TSAN_CALLBACKS)
65   callback_write(ref, __builtin_return_address(0), tag);
66 #endif
67   ref->_another = val;
68 }
69