// This file is used from other tests. // RUN: true #include #include #include 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; }