|  | // This file is used from other tests. | 
|  | // RUN: true | 
|  |  | 
|  | #include <dlfcn.h> | 
|  | #include <stdio.h> | 
|  | #include <stdlib.h> | 
|  |  | 
|  | struct MyObject; | 
|  | typedef MyObject *MyObjectRef; | 
|  | extern "C" { | 
|  | void InitializeLibrary(); | 
|  | MyObject *ObjectCreate(); | 
|  | long ObjectRead(MyObject *); | 
|  | void ObjectWrite(MyObject *, long); | 
|  | void ObjectWriteAnother(MyObject *, long); | 
|  | } | 
|  |  | 
|  | struct MyObject { | 
|  | long _val; | 
|  | long _another; | 
|  | }; | 
|  |  | 
|  | #if defined(USE_TSAN_CALLBACKS) | 
|  | static void *tag; | 
|  | void *(*callback_register_tag)(const char *object_type); | 
|  | void *(*callback_assign_tag)(void *addr, void *tag); | 
|  | void (*callback_read)(void *addr, void *caller_pc, void *tag); | 
|  | void (*callback_write)(void *addr, void *caller_pc, void *tag); | 
|  | #endif | 
|  |  | 
|  | void InitializeLibrary() { | 
|  | #if defined(USE_TSAN_CALLBACKS) | 
|  | callback_register_tag = (decltype(callback_register_tag))dlsym(RTLD_DEFAULT, "__tsan_external_register_tag"); | 
|  | callback_assign_tag = (decltype(callback_assign_tag))dlsym(RTLD_DEFAULT, "__tsan_external_assign_tag"); | 
|  | callback_read = (decltype(callback_read))dlsym(RTLD_DEFAULT, "__tsan_external_read"); | 
|  | callback_write = (decltype(callback_write))dlsym(RTLD_DEFAULT, "__tsan_external_write"); | 
|  | tag = callback_register_tag("MyLibrary::MyObject"); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | MyObject *ObjectCreate() { | 
|  | MyObject *ref = (MyObject *)malloc(sizeof(MyObject)); | 
|  | #if defined(USE_TSAN_CALLBACKS) | 
|  | callback_assign_tag(ref, tag); | 
|  | #endif | 
|  | return ref; | 
|  | } | 
|  |  | 
|  | long ObjectRead(MyObject *ref) { | 
|  | #if defined(USE_TSAN_CALLBACKS) | 
|  | callback_read(ref, __builtin_return_address(0), tag); | 
|  | #endif | 
|  | return ref->_val; | 
|  | } | 
|  |  | 
|  | void ObjectWrite(MyObject *ref, long val) { | 
|  | #if defined(USE_TSAN_CALLBACKS) | 
|  | callback_write(ref, __builtin_return_address(0), tag); | 
|  | #endif | 
|  | ref->_val = val; | 
|  | } | 
|  |  | 
|  | void ObjectWriteAnother(MyObject *ref, long val) { | 
|  | #if defined(USE_TSAN_CALLBACKS) | 
|  | callback_write(ref, __builtin_return_address(0), tag); | 
|  | #endif | 
|  | ref->_another = val; | 
|  | } |