Bill Schmidt 2979162732 [PPC64, TSAN] LLVM basic enablement of thread sanitizer for PPC64 (BE and LE)
This patch is by Simone Atzeni with portions by Adhemerval Zanella.

This contains the LLVM patches to enable the thread sanitizer for
PPC64, both big- and little-endian.  Two different virtual memory
sizes are supported:  Old kernels use a 44-bit address space, while
newer kernels require a 46-bit address space.

There are two companion patches that will be added shortly.  There is
a Clang patch to actually turn on the use of the thread sanitizer for
PPC64.  There is also a patch that I wrote to provide interceptor
support for setjmp/longjmp on PPC64.

Patch discussion at reviews.llvm.org/D12841.

llvm-svn: 255057
2015-12-08 21:54:39 +00:00

70 lines
1.9 KiB
C

#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <dlfcn.h>
#include <stddef.h>
#include <sched.h>
#include <stdarg.h>
#ifdef __APPLE__
#include <mach/mach_time.h>
#endif
// TSan-invisible barrier.
// Tests use it to establish necessary execution order in a way that does not
// interfere with tsan (does not establish synchronization between threads).
typedef unsigned long long invisible_barrier_t;
#ifdef __cplusplus
extern "C" {
#endif
void __tsan_testonly_barrier_init(invisible_barrier_t *barrier,
unsigned count);
void __tsan_testonly_barrier_wait(invisible_barrier_t *barrier);
#ifdef __cplusplus
}
#endif
static inline void barrier_init(invisible_barrier_t *barrier, unsigned count) {
__tsan_testonly_barrier_init(barrier, count);
}
static inline void barrier_wait(invisible_barrier_t *barrier) {
__tsan_testonly_barrier_wait(barrier);
}
// Default instance of the barrier, but a test can declare more manually.
invisible_barrier_t barrier;
void print_address(const char *str, int n, ...) {
fprintf(stderr, "%s", str);
va_list ap;
va_start(ap, n);
while (n--) {
void *p = va_arg(ap, void *);
#if defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__)
// On FreeBSD, the %p conversion specifier works as 0x%x and thus does not
// match to the format used in the diagnotic message.
fprintf(stderr, "0x%012lx ", (unsigned long) p);
#elif defined(__mips64)
fprintf(stderr, "0x%010lx ", (unsigned long) p);
#endif
}
fprintf(stderr, "\n");
}
#ifdef __APPLE__
unsigned long long monotonic_clock_ns() {
static mach_timebase_info_data_t timebase_info;
if (timebase_info.denom == 0) mach_timebase_info(&timebase_info);
return (mach_absolute_time() * timebase_info.numer) / timebase_info.denom;
}
#else
unsigned long long monotonic_clock_ns() {
struct timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
return (unsigned long long)t.tv_sec * 1000000000ull + t.tv_nsec;
}
#endif