Loading...
--- /dev/null
+++ libmalloc/libmalloc-792.1.1/tests/tsan.c
@@ -0,0 +1,98 @@
+#include <darwintest.h>
+#include <dlfcn.h>
+#include <pthread.h>
+#include <stdlib.h>
+
+T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true), T_META_TAG_VM_NOT_PREFERRED);
+
+T_DECL(tsan_sanity, "TSan Sanity Check", T_META_CHECK_LEAKS(NO))
+{
+ void *tsan_dylib = dlopen("@rpath/libclang_rt.tsan_osx_dynamic.dylib", RTLD_NOLOAD);
+ T_ASSERT_NOTNULL(tsan_dylib, "TSan dylib loaded");
+
+ void *ptr = malloc(16);
+ free(ptr);
+
+ T_PASS("I didn't crash!");
+}
+
+typedef unsigned long long invisible_barrier_t;
+void __tsan_testonly_barrier_init(invisible_barrier_t *barrier, unsigned count);
+void __tsan_testonly_barrier_wait(invisible_barrier_t *barrier);
+int __tsan_get_report_data(void *report, const char **description, int *count,
+ int *stack_count, int *mop_count, int *loc_count,
+ int *mutex_count, int *thread_count,
+ int *unique_tid_count, void **sleep_trace,
+ unsigned long trace_size);
+
+bool tsan_report_hit = false;
+char *tsan_description = NULL;
+invisible_barrier_t barrier;
+
+__attribute__((weak))
+const char *__tsan_default_options() {
+ return "abort_on_error=0:exitcode=0";
+}
+
+__attribute__((weak))
+void __tsan_on_report(void *report) {
+ tsan_report_hit = true;
+
+ const char *description;
+ int count;
+ int stack_count, mop_count, loc_count, mutex_count, thread_count,
+ unique_tid_count;
+ void *sleep_trace[16] = {0};
+ __tsan_get_report_data(report, &description, &count, &stack_count, &mop_count,
+ &loc_count, &mutex_count, &thread_count,
+ &unique_tid_count, sleep_trace, 16);
+ tsan_description = strdup(description);
+}
+
+void *thread1(void *arg) {
+ __tsan_testonly_barrier_wait(&barrier);
+ *((long *)arg) = 42;
+ return NULL;
+}
+
+void *thread2(void *arg) {
+ *((long *)arg) = 43;
+ __tsan_testonly_barrier_wait(&barrier);
+ return NULL;
+}
+
+T_DECL(tsan_data_race_stack, "TSan Detects data-race on stack", T_META_CHECK_LEAKS(NO))
+{
+ tsan_description = NULL;
+ tsan_report_hit = false;
+ __tsan_testonly_barrier_init(&barrier, 2);
+
+ long racy_stack_value = 0;
+ pthread_t t1;
+ pthread_create(&t1, NULL, thread1, &racy_stack_value);
+ pthread_t t2;
+ pthread_create(&t2, NULL, thread2, &racy_stack_value);
+ pthread_join(t2, NULL);
+ pthread_join(t1, NULL);
+
+ T_ASSERT_EQ(tsan_report_hit, true, "tsan finds data-race");
+ T_EXPECT_NOTNULL(strstr(tsan_description, "data-race"), "tsan header");
+}
+
+T_DECL(tsan_data_race_heap, "TSan Detects data-race on heap", T_META_CHECK_LEAKS(NO))
+{
+ tsan_description = NULL;
+ tsan_report_hit = false;
+ __tsan_testonly_barrier_init(&barrier, 2);
+
+ long *racy_heap_value = malloc(sizeof(long));
+ pthread_t t1;
+ pthread_create(&t1, NULL, thread1, racy_heap_value);
+ pthread_t t2;
+ pthread_create(&t2, NULL, thread2, racy_heap_value);
+ pthread_join(t2, NULL);
+ pthread_join(t1, NULL);
+
+ T_ASSERT_EQ(tsan_report_hit, true, "tsan finds data-race");
+ T_EXPECT_NOTNULL(strstr(tsan_description, "data-race"), "tsan header");
+}