<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Hopefully, r263137 fixes it.</div><div class=""><br class=""></div><div class="">Kuba</div><br class=""><div><blockquote type="cite" class=""><div class="">On 10 Mar 2016, at 19:07, Chandler Carruth <<a href="mailto:chandlerc@google.com" class="">chandlerc@google.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">While it isn't blamed for it, I think this is failing on all the bots:<div class=""><br class=""></div><div class=""><a href="http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-debian-fast/builds/36295" class="">http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-debian-fast/builds/36295</a><br class=""></div><div class=""><a href="http://lab.llvm.org:8011/builders/clang-ppc64be-linux/builds/2170" class="">http://lab.llvm.org:8011/builders/clang-ppc64be-linux/builds/2170</a><br class=""></div></div><br class=""><div class="gmail_quote"><div dir="ltr" class="">On Thu, Mar 10, 2016 at 6:05 PM Kuba Brecka via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" class="">llvm-commits@lists.llvm.org</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: kuba.brecka<br class="">
Date: Thu Mar 10 11:00:29 2016<br class="">
New Revision: 263126<br class="">
<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=263126&view=rev" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project?rev=263126&view=rev</a><br class="">
Log:<br class="">
[tsan] Add TSan debugger APIs<br class="">
<br class="">
Currently, TSan only reports everything in a formatted textual form. The idea behind this patch is to provide a consistent API that can be used to query information contained in a TSan-produced report. User can use these APIs either in a debugger (via a script or directly), or they can use it directly from the process (e.g. in the __tsan_on_report callback). ASan already has a similar API, see <a href="http://reviews.llvm.org/D4466" rel="noreferrer" target="_blank" class="">http://reviews.llvm.org/D4466</a>.<br class="">
<br class="">
Differential Revision: <a href="http://reviews.llvm.org/D16191" rel="noreferrer" target="_blank" class="">http://reviews.llvm.org/D16191</a><br class="">
<br class="">
<br class="">
Added:<br class="">
    compiler-rt/trunk/lib/tsan/rtl/tsan_debugging.cc<br class="">
    compiler-rt/trunk/test/tsan/<a href="http://debugging.cc" class="">debugging.cc</a><br class="">
Modified:<br class="">
    compiler-rt/trunk/lib/tsan/CMakeLists.txt<br class="">
    compiler-rt/trunk/lib/tsan/rtl/tsan_interface.h<br class="">
    compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h<br class="">
    compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc<br class="">
<br class="">
Modified: compiler-rt/trunk/lib/tsan/CMakeLists.txt<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/CMakeLists.txt?rev=263126&r1=263125&r2=263126&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/CMakeLists.txt?rev=263126&r1=263125&r2=263126&view=diff</a><br class="">
==============================================================================<br class="">
--- compiler-rt/trunk/lib/tsan/CMakeLists.txt (original)<br class="">
+++ compiler-rt/trunk/lib/tsan/CMakeLists.txt Thu Mar 10 11:00:29 2016<br class="">
@@ -24,6 +24,7 @@ append_list_if(COMPILER_RT_HAS_WGLOBAL_C<br class="">
<br class="">
 set(TSAN_SOURCES<br class="">
   rtl/tsan_clock.cc<br class="">
+  rtl/tsan_debugging.cc<br class="">
   rtl/tsan_flags.cc<br class="">
   rtl/tsan_fd.cc<br class="">
   rtl/tsan_ignoreset.cc<br class="">
<br class="">
Added: compiler-rt/trunk/lib/tsan/rtl/tsan_debugging.cc<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_debugging.cc?rev=263126&view=auto" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_debugging.cc?rev=263126&view=auto</a><br class="">
==============================================================================<br class="">
--- compiler-rt/trunk/lib/tsan/rtl/tsan_debugging.cc (added)<br class="">
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_debugging.cc Thu Mar 10 11:00:29 2016<br class="">
@@ -0,0 +1,162 @@<br class="">
+//===-- tsan_debugging.cc -------------------------------------------------===//<br class="">
+//<br class="">
+//                     The LLVM Compiler Infrastructure<br class="">
+//<br class="">
+// This file is distributed under the University of Illinois Open Source<br class="">
+// License. See LICENSE.TXT for details.<br class="">
+//<br class="">
+//===----------------------------------------------------------------------===//<br class="">
+//<br class="">
+// This file is a part of ThreadSanitizer (TSan), a race detector.<br class="">
+//<br class="">
+// TSan debugging API implementation.<br class="">
+//===----------------------------------------------------------------------===//<br class="">
+#include "tsan_interface.h"<br class="">
+#include "tsan_report.h"<br class="">
+#include "tsan_rtl.h"<br class="">
+<br class="">
+using namespace __tsan;<br class="">
+<br class="">
+static const char *ReportTypeDescription(ReportType typ) {<br class="">
+  if (typ == ReportTypeRace) return "data-race";<br class="">
+  if (typ == ReportTypeVptrRace) return "data-race-vptr";<br class="">
+  if (typ == ReportTypeUseAfterFree) return "heap-use-after-free";<br class="">
+  if (typ == ReportTypeVptrUseAfterFree) return "heap-use-after-free-vptr";<br class="">
+  if (typ == ReportTypeThreadLeak) return "thread-leak";<br class="">
+  if (typ == ReportTypeMutexDestroyLocked) return "locked-mutex-destroy";<br class="">
+  if (typ == ReportTypeMutexDoubleLock) return "mutex-double-lock";<br class="">
+  if (typ == ReportTypeMutexBadUnlock) return "mutex-bad-unlock";<br class="">
+  if (typ == ReportTypeMutexBadReadLock) return "mutex-bad-read-lock";<br class="">
+  if (typ == ReportTypeMutexBadReadUnlock) return "mutex-bad-read-unlock";<br class="">
+  if (typ == ReportTypeSignalUnsafe) return "signal-unsafe-call";<br class="">
+  if (typ == ReportTypeErrnoInSignal) return "errno-in-signal-handler";<br class="">
+  if (typ == ReportTypeDeadlock) return "lock-order-inversion";<br class="">
+  return "";<br class="">
+}<br class="">
+<br class="">
+static const char *ReportLocationTypeDescription(ReportLocationType typ) {<br class="">
+  if (typ == ReportLocationGlobal) return "global";<br class="">
+  if (typ == ReportLocationHeap) return "heap";<br class="">
+  if (typ == ReportLocationStack) return "stack";<br class="">
+  if (typ == ReportLocationTLS) return "tls";<br class="">
+  if (typ == ReportLocationFD) return "fd";<br class="">
+  return "";<br class="">
+}<br class="">
+<br class="">
+static void CopyTrace(SymbolizedStack *first_frame, void **trace,<br class="">
+                      uptr trace_size) {<br class="">
+  uptr i = 0;<br class="">
+  for (SymbolizedStack *frame = first_frame; frame != nullptr;<br class="">
+       frame = frame->next) {<br class="">
+    trace[i++] = (void *)frame->info.address;<br class="">
+    if (i >= trace_size) break;<br class="">
+  }<br class="">
+}<br class="">
+<br class="">
+// Meant to be called by the debugger.<br class="">
+SANITIZER_INTERFACE_ATTRIBUTE<br class="">
+void *__tsan_get_current_report() {<br class="">
+  const ReportDesc *rep = cur_thread()->current_report;<br class="">
+  return (void *)rep;<br class="">
+}<br class="">
+<br class="">
+SANITIZER_INTERFACE_ATTRIBUTE<br class="">
+int __tsan_get_report_data(void *report, const char **description, int *count,<br class="">
+                           int *stack_count, int *mop_count, int *loc_count,<br class="">
+                           int *mutex_count, int *thread_count,<br class="">
+                           int *unique_tid_count, void **sleep_trace,<br class="">
+                           uptr trace_size) {<br class="">
+  const ReportDesc *rep = (ReportDesc *)report;<br class="">
+  *description = ReportTypeDescription(rep->typ);<br class="">
+  *count = rep->count;<br class="">
+  *stack_count = rep->stacks.Size();<br class="">
+  *mop_count = rep->mops.Size();<br class="">
+  *loc_count = rep->locs.Size();<br class="">
+  *mutex_count = rep->mutexes.Size();<br class="">
+  *thread_count = rep->threads.Size();<br class="">
+  *unique_tid_count = rep->unique_tids.Size();<br class="">
+  if (rep->sleep) CopyTrace(rep->sleep->frames, sleep_trace, trace_size);<br class="">
+  return 1;<br class="">
+}<br class="">
+<br class="">
+SANITIZER_INTERFACE_ATTRIBUTE<br class="">
+int __tsan_get_report_stack(void *report, uptr idx, void **trace,<br class="">
+                            uptr trace_size) {<br class="">
+  const ReportDesc *rep = (ReportDesc *)report;<br class="">
+  CHECK_LT(idx, rep->stacks.Size());<br class="">
+  ReportStack *stack = rep->stacks[idx];<br class="">
+  CopyTrace(stack->frames, trace, trace_size);<br class="">
+  return 1;<br class="">
+}<br class="">
+<br class="">
+SANITIZER_INTERFACE_ATTRIBUTE<br class="">
+int __tsan_get_report_mop(void *report, uptr idx, int *tid, void **addr,<br class="">
+                          int *size, int *write, int *atomic, void **trace,<br class="">
+                          uptr trace_size) {<br class="">
+  const ReportDesc *rep = (ReportDesc *)report;<br class="">
+  CHECK_LT(idx, rep->mops.Size());<br class="">
+  ReportMop *mop = rep->mops[idx];<br class="">
+  *tid = mop->tid;<br class="">
+  *addr = (void *)mop->addr;<br class="">
+  *size = mop->size;<br class="">
+  *write = mop->write ? 1 : 0;<br class="">
+  *atomic = mop->atomic ? 1 : 0;<br class="">
+  CopyTrace(mop->stack->frames, trace, trace_size);<br class="">
+  return 1;<br class="">
+}<br class="">
+<br class="">
+SANITIZER_INTERFACE_ATTRIBUTE<br class="">
+int __tsan_get_report_loc(void *report, uptr idx, const char **type,<br class="">
+                          void **addr, uptr *start, uptr *size, int *tid,<br class="">
+                          int *fd, int *suppressable, void **trace,<br class="">
+                          uptr trace_size) {<br class="">
+  const ReportDesc *rep = (ReportDesc *)report;<br class="">
+  CHECK_LT(idx, rep->locs.Size());<br class="">
+  ReportLocation *loc = rep->locs[idx];<br class="">
+  *type = ReportLocationTypeDescription(loc->type);<br class="">
+  *addr = (void *)loc->global.start;<br class="">
+  *start = loc->heap_chunk_start;<br class="">
+  *size = loc->heap_chunk_size;<br class="">
+  *tid = loc->tid;<br class="">
+  *fd = loc->fd;<br class="">
+  *suppressable = loc->suppressable;<br class="">
+  if (loc->stack) CopyTrace(loc->stack->frames, trace, trace_size);<br class="">
+  return 1;<br class="">
+}<br class="">
+<br class="">
+SANITIZER_INTERFACE_ATTRIBUTE<br class="">
+int __tsan_get_report_mutex(void *report, uptr idx, uptr *mutex_id, void **addr,<br class="">
+                            int *destroyed, void **trace, uptr trace_size) {<br class="">
+  const ReportDesc *rep = (ReportDesc *)report;<br class="">
+  CHECK_LT(idx, rep->mutexes.Size());<br class="">
+  ReportMutex *mutex = rep->mutexes[idx];<br class="">
+  *mutex_id = mutex->id;<br class="">
+  *addr = (void *)mutex->addr;<br class="">
+  *destroyed = mutex->destroyed;<br class="">
+  CopyTrace(mutex->stack->frames, trace, trace_size);<br class="">
+  return 1;<br class="">
+}<br class="">
+<br class="">
+SANITIZER_INTERFACE_ATTRIBUTE<br class="">
+int __tsan_get_report_thread(void *report, uptr idx, int *tid, uptr *pid,<br class="">
+                             int *running, const char **name, int *parent_tid,<br class="">
+                             void **trace, uptr trace_size) {<br class="">
+  const ReportDesc *rep = (ReportDesc *)report;<br class="">
+  CHECK_LT(idx, rep->threads.Size());<br class="">
+  ReportThread *thread = rep->threads[idx];<br class="">
+  *tid = thread->id;<br class="">
+  *pid = thread->pid;<br class="">
+  *running = thread->running;<br class="">
+  *name = thread->name;<br class="">
+  *parent_tid = thread->parent_tid;<br class="">
+  CopyTrace(thread->stack->frames, trace, trace_size);<br class="">
+  return 1;<br class="">
+}<br class="">
+<br class="">
+SANITIZER_INTERFACE_ATTRIBUTE<br class="">
+int __tsan_get_report_unique_tid(void *report, uptr idx, int *tid) {<br class="">
+  const ReportDesc *rep = (ReportDesc *)report;<br class="">
+  CHECK_LT(idx, rep->unique_tids.Size());<br class="">
+  *tid = rep->unique_tids[idx];<br class="">
+  return 1;<br class="">
+}<br class="">
<br class="">
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interface.h<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interface.h?rev=263126&r1=263125&r2=263126&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interface.h?rev=263126&r1=263125&r2=263126&view=diff</a><br class="">
==============================================================================<br class="">
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interface.h (original)<br class="">
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interface.h Thu Mar 10 11:00:29 2016<br class="">
@@ -75,6 +75,61 @@ void __tsan_read_range(void *addr, unsig<br class="">
 SANITIZER_INTERFACE_ATTRIBUTE<br class="">
 void __tsan_write_range(void *addr, unsigned long size);  // NOLINT<br class="">
<br class="">
+// User may provide function that would be called right when TSan detects<br class="">
+// an error. The argument 'report' is an opaque pointer that can be used to<br class="">
+// gather additional information using other TSan report API functions.<br class="">
+SANITIZER_INTERFACE_ATTRIBUTE<br class="">
+void __tsan_on_report(void *report);<br class="">
+<br class="">
+// If TSan is currently reporting a detected issue on the current thread,<br class="">
+// returns an opaque pointer to the current report. Otherwise returns NULL.<br class="">
+SANITIZER_INTERFACE_ATTRIBUTE<br class="">
+void *__tsan_get_current_report();<br class="">
+<br class="">
+// Returns a report's description (issue type), number of duplicate issues<br class="">
+// found, counts of array data (stack traces, memory operations, locations,<br class="">
+// mutexes, threads, unique thread IDs) and a stack trace of a sleep() call (if<br class="">
+// one was involved in the issue).<br class="">
+SANITIZER_INTERFACE_ATTRIBUTE<br class="">
+int __tsan_get_report_data(void *report, const char **description, int *count,<br class="">
+                           int *stack_count, int *mop_count, int *loc_count,<br class="">
+                           int *mutex_count, int *thread_count,<br class="">
+                           int *unique_tid_count, void **sleep_trace,<br class="">
+                           uptr trace_size);<br class="">
+<br class="">
+// Returns information about stack traces included in the report.<br class="">
+SANITIZER_INTERFACE_ATTRIBUTE<br class="">
+int __tsan_get_report_stack(void *report, uptr idx, void **trace,<br class="">
+                            uptr trace_size);<br class="">
+<br class="">
+// Returns information about memory operations included in the report.<br class="">
+SANITIZER_INTERFACE_ATTRIBUTE<br class="">
+int __tsan_get_report_mop(void *report, uptr idx, int *tid, void **addr,<br class="">
+                          int *size, int *write, int *atomic, void **trace,<br class="">
+                          uptr trace_size);<br class="">
+<br class="">
+// Returns information about locations included in the report.<br class="">
+SANITIZER_INTERFACE_ATTRIBUTE<br class="">
+int __tsan_get_report_loc(void *report, uptr idx, const char **type,<br class="">
+                          void **addr, uptr *start, uptr *size, int *tid,<br class="">
+                          int *fd, int *suppressable, void **trace,<br class="">
+                          uptr trace_size);<br class="">
+<br class="">
+// Returns information about mutexes included in the report.<br class="">
+SANITIZER_INTERFACE_ATTRIBUTE<br class="">
+int __tsan_get_report_mutex(void *report, uptr idx, uptr *mutex_id, void **addr,<br class="">
+                            int *destroyed, void **trace, uptr trace_size);<br class="">
+<br class="">
+// Returns information about threads included in the report.<br class="">
+SANITIZER_INTERFACE_ATTRIBUTE<br class="">
+int __tsan_get_report_thread(void *report, uptr idx, int *tid, uptr *pid,<br class="">
+                             int *running, const char **name, int *parent_tid,<br class="">
+                             void **trace, uptr trace_size);<br class="">
+<br class="">
+// Returns information about unique thread IDs included in the report.<br class="">
+SANITIZER_INTERFACE_ATTRIBUTE<br class="">
+int __tsan_get_report_unique_tid(void *report, uptr idx, int *tid);<br class="">
+<br class="">
 #ifdef __cplusplus<br class="">
 }  // extern "C"<br class="">
 #endif<br class="">
<br class="">
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h?rev=263126&r1=263125&r2=263126&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h?rev=263126&r1=263125&r2=263126&view=diff</a><br class="">
==============================================================================<br class="">
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h (original)<br class="">
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h Thu Mar 10 11:00:29 2016<br class="">
@@ -404,6 +404,8 @@ struct ThreadState {<br class="">
   // If set, malloc must not be called.<br class="">
   int nomalloc;<br class="">
<br class="">
+  const ReportDesc *current_report;<br class="">
+<br class="">
   explicit ThreadState(Context *ctx, int tid, int unique_id, u64 epoch,<br class="">
                        unsigned reuse_count,<br class="">
                        uptr stk_addr, uptr stk_size,<br class="">
<br class="">
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc?rev=263126&r1=263125&r2=263126&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc?rev=263126&r1=263125&r2=263126&view=diff</a><br class="">
==============================================================================<br class="">
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc (original)<br class="">
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc Thu Mar 10 11:00:29 2016<br class="">
@@ -56,6 +56,11 @@ bool OnReport(const ReportDesc *rep, boo<br class="">
 }<br class="">
 #endif<br class="">
<br class="">
+SANITIZER_WEAK_DEFAULT_IMPL<br class="">
+void __tsan_on_report(const ReportDesc *rep) {<br class="">
+  (void)rep;<br class="">
+}<br class="">
+<br class="">
 static void StackStripMain(SymbolizedStack *frames) {<br class="">
   SymbolizedStack *last_frame = nullptr;<br class="">
   SymbolizedStack *last_frame2 = nullptr;<br class="">
@@ -492,6 +497,8 @@ bool OutputReport(ThreadState *thr, cons<br class="">
     return false;<br class="">
   atomic_store_relaxed(&ctx->last_symbolize_time_ns, NanoTime());<br class="">
   const ReportDesc *rep = srep.GetReport();<br class="">
+  CHECK_EQ(thr->current_report, nullptr);<br class="">
+  thr->current_report = rep;<br class="">
   Suppression *supp = 0;<br class="">
   uptr pc_or_addr = 0;<br class="">
   for (uptr i = 0; pc_or_addr == 0 && i < rep->mops.Size(); i++)<br class="">
@@ -512,13 +519,17 @@ bool OutputReport(ThreadState *thr, cons<br class="">
     thr->is_freeing = false;<br class="">
     bool suppressed = OnReport(rep, pc_or_addr != 0);<br class="">
     thr->is_freeing = old_is_freeing;<br class="">
-    if (suppressed)<br class="">
+    if (suppressed) {<br class="">
+      thr->current_report = nullptr;<br class="">
       return false;<br class="">
+    }<br class="">
   }<br class="">
   PrintReport(rep);<br class="">
+  __tsan_on_report(rep);<br class="">
   ctx->nreported++;<br class="">
   if (flags()->halt_on_error)<br class="">
     Die();<br class="">
+  thr->current_report = nullptr;<br class="">
   return true;<br class="">
 }<br class="">
<br class="">
<br class="">
Added: compiler-rt/trunk/test/tsan/<a href="http://debugging.cc" class="">debugging.cc</a><br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/debugging.cc?rev=263126&view=auto" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/debugging.cc?rev=263126&view=auto</a><br class="">
==============================================================================<br class="">
--- compiler-rt/trunk/test/tsan/<a href="http://debugging.cc" class="">debugging.cc</a> (added)<br class="">
+++ compiler-rt/trunk/test/tsan/<a href="http://debugging.cc" class="">debugging.cc</a> Thu Mar 10 11:00:29 2016<br class="">
@@ -0,0 +1,88 @@<br class="">
+// RUN: %clangxx_tsan -O1 %s -o %t<br class="">
+// RUN: %deflake %run %t 2>&1 | FileCheck %s<br class="">
+<br class="">
+#include <pthread.h><br class="">
+#include <stdio.h><br class="">
+#include <stdlib.h><br class="">
+#include <string.h><br class="">
+<br class="">
+#include "test.h"<br class="">
+<br class="">
+extern "C" {<br class="">
+void __tsan_on_report(void *report);<br class="">
+void *__tsan_get_current_report();<br class="">
+int __tsan_get_report_data(void *report, const char **description, int *count,<br class="">
+                           int *stack_count, int *mop_count, int *loc_count,<br class="">
+                           int *mutex_count, int *thread_count,<br class="">
+                           int *unique_tid_count, void **sleep_trace,<br class="">
+                           unsigned long trace_size);<br class="">
+int __tsan_get_report_mop(void *report, unsigned long idx, int *tid,<br class="">
+                          void **addr, int *size, int *write, int *atomic,<br class="">
+                          void **trace, unsigned long trace_size);<br class="">
+}<br class="">
+<br class="">
+long my_global;<br class="">
+<br class="">
+void *Thread(void *a) {<br class="">
+  barrier_wait(&barrier);<br class="">
+  my_global = 42;<br class="">
+  return NULL;<br class="">
+}<br class="">
+<br class="">
+int main() {<br class="">
+  barrier_init(&barrier, 2);<br class="">
+  fprintf(stderr, "&my_global = %p\n", &my_global);<br class="">
+  // CHECK: &my_global = [[GLOBAL:0x[0-9a-f]+]]<br class="">
+  pthread_t t;<br class="">
+  pthread_create(&t, 0, Thread, 0);<br class="">
+  my_global = 41;<br class="">
+  barrier_wait(&barrier);<br class="">
+  pthread_join(t, 0);<br class="">
+  fprintf(stderr, "Done.\n");<br class="">
+}<br class="">
+<br class="">
+void __tsan_on_report(void *report) {<br class="">
+  fprintf(stderr, "__tsan_on_report(%p)\n", report);<br class="">
+  fprintf(stderr, "__tsan_get_current_report() = %p\n",<br class="">
+          __tsan_get_current_report());<br class="">
+  // CHECK: __tsan_on_report([[REPORT:0x[0-9a-f]+]])<br class="">
+  // CHECK: __tsan_get_current_report() = [[REPORT]]<br class="">
+<br class="">
+  const char *description;<br class="">
+  int count;<br class="">
+  int stack_count, mop_count, loc_count, mutex_count, thread_count,<br class="">
+      unique_tid_count;<br class="">
+  void *sleep_trace[16] = {0};<br class="">
+  __tsan_get_report_data(report, &description, &count, &stack_count, &mop_count,<br class="">
+                         &loc_count, &mutex_count, &thread_count,<br class="">
+                         &unique_tid_count, sleep_trace, 16);<br class="">
+  fprintf(stderr, "report type = '%s', count = %d\n", description, count);<br class="">
+  // CHECK: report type = 'data-race', count = 0<br class="">
+<br class="">
+  fprintf(stderr, "mop_count = %d\n", mop_count);<br class="">
+  // CHECK: mop_count = 2<br class="">
+<br class="">
+  int tid;<br class="">
+  void *addr;<br class="">
+  int size, write, atomic;<br class="">
+  void *trace[16] = {0};<br class="">
+<br class="">
+  __tsan_get_report_mop(report, 0, &tid, &addr, &size, &write, &atomic, trace,<br class="">
+                        16);<br class="">
+  fprintf(stderr, "tid = %d, addr = %p, size = %d, write = %d, atomic = %d\n",<br class="">
+          tid, addr, size, write, atomic);<br class="">
+  // CHECK: tid = 1, addr = [[GLOBAL]], size = 8, write = 1, atomic = 0<br class="">
+  fprintf(stderr, "trace[0] = %p, trace[1] = %p\n", trace[0], trace[1]);<br class="">
+  // CHECK: trace[0] = 0x{{[0-9a-f]+}}, trace[1] = 0x0<br class="">
+<br class="">
+  __tsan_get_report_mop(report, 1, &tid, &addr, &size, &write, &atomic, trace,<br class="">
+                        16);<br class="">
+  fprintf(stderr, "tid = %d, addr = %p, size = %d, write = %d, atomic = %d\n",<br class="">
+          tid, addr, size, write, atomic);<br class="">
+  // CHECK: tid = 0, addr = [[GLOBAL]], size = 8, write = 1, atomic = 0<br class="">
+  fprintf(stderr, "trace[0] = %p, trace[1] = %p\n", trace[0], trace[1]);<br class="">
+  // CHECK: trace[0] = 0x{{[0-9a-f]+}}, trace[1] = 0x0<br class="">
+}<br class="">
+<br class="">
+// CHECK: Done.<br class="">
+// CHECK: ThreadSanitizer: reported 1 warnings<br class="">
<br class="">
<br class="">
_______________________________________________<br class="">
llvm-commits mailing list<br class="">
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank" class="">llvm-commits@lists.llvm.org</a><br class="">
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank" class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br class="">
</blockquote></div>
</div></blockquote></div><br class=""></body></html>