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