#include <cassert> // assert()
#include <climits> // PTHREAD_STACK_MIN
-#include <iostream> // std::cout
+#include <iostream> // std::cerr
#include <stdlib.h> // atoi()
#ifdef _WIN32
#include <process.h> // _beginthreadex()
#else
#include <pthread.h> // pthread_mutex_t
#endif
-#include "../../drd/drd.h"
+#include "unified_annotations.h"
+
+
+static bool s_enable_annotations = true;
#ifdef _WIN32
{
if (m_count_ptr)
{
- ANNOTATE_HAPPENS_BEFORE(m_count_ptr);
+ if (s_enable_annotations)
+ ANNOTATE_HAPPENS_BEFORE(m_count_ptr);
if (--(*m_count_ptr) == 0)
{
- ANNOTATE_HAPPENS_AFTER(m_count_ptr);
+ if (s_enable_annotations)
+ {
+ ANNOTATE_HAPPENS_AFTER(m_count_ptr);
+ ANNOTATE_HAPPENS_DONE(m_count_ptr);
+ }
delete m_ptr;
m_ptr = NULL;
delete m_count_ptr;
int main(int argc, char** argv)
{
- smart_ptr<counter> p(new counter);
const int nthreads = std::max(argc > 1 ? atoi(argv[1]) : 1, 1);
- Thread T[nthreads];
-
- p->post_increment();
- for (int i = 0; i < nthreads; ++i)
- T[i].Create(thread_func, new smart_ptr<counter>(p));
- p = NULL;
- for (int i = 0; i < nthreads; ++i)
- T[i].Join();
- std::cout << "Done.\n";
+ const int iterations = std::max(argc > 2 ? atoi(argv[2]) : 1, 1);
+ s_enable_annotations = argc > 3 ? !!atoi(argv[3]) : true;
+
+ for (int j = 0; j < iterations; ++j)
+ {
+ Thread T[nthreads];
+
+ smart_ptr<counter> p(new counter);
+ p->post_increment();
+ for (int i = 0; i < nthreads; ++i)
+ T[i].Create(thread_func, new smart_ptr<counter>(p));
+ p = NULL;
+ for (int i = 0; i < nthreads; ++i)
+ T[i].Join();
+ }
+ std::cerr << "Done.\n";
return 0;
}
--- /dev/null
+#ifndef _UNIFIED_ANNOTATIONS_H_
+#define _UNIFIED_ANNOTATIONS_H_
+
+
+#include "../../drd/drd.h"
+
+
+/*
+ * Redefine the happens before/after/done annotation macros such that these
+ * can be intercepted by DRD, Helgrind and ThreadSanitizer. See also
+ * http://code.google.com/p/data-race-test/source/browse/trunk/dynamic_annotations/dynamic_annotations.h
+ */
+#undef ANNOTATE_HAPPENS_BEFORE
+#define ANNOTATE_HAPPENS_BEFORE(addr) \
+ do { \
+ DRDCL_(annotate_happens_before)(addr); \
+ AnnotateCondVarSignal(__FILE__, __LINE__, addr); \
+ } while(0)
+#undef ANNOTATE_HAPPENS_AFTER
+#define ANNOTATE_HAPPENS_AFTER(addr) \
+ do { \
+ DRDCL_(annotate_happens_after)(addr); \
+ AnnotateCondVarWait(__FILE__, __LINE__, addr, NULL); \
+ } while(0)
+#undef ANNOTATE_HAPPENS_DONE
+#define ANNOTATE_HAPPENS_DONE(addr) \
+ do { \
+ DRDCL_(annotate_happens_done)(addr); \
+ } while(0)
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if 0
+}
+#endif
+
+
+void __attribute__((weak,noinline))
+AnnotateCondVarSignal(const char *file, int line, const volatile void *cv)
+{
+ asm("");
+}
+
+void __attribute__((weak,noinline))
+AnnotateCondVarWait(const char *file, int line, const volatile void *cv,
+ const volatile void *lock)
+{
+ asm("");
+}
+
+
+#if 0
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _UNIFIED_ANNOTATIONS_H_ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 2
+ * End:
+ */