// 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;
}