diff options
| author | Eric Fiselier <eric@efcs.ca> | 2016-07-19 23:07:03 +0000 |
|---|---|---|
| committer | Eric Fiselier <eric@efcs.ca> | 2016-07-19 23:07:03 +0000 |
| commit | b08d8b189c0a3a7c92242836767383721ad7e89d (patch) | |
| tree | 9f925b2743ea910a1add974c59012883e17f339a /libcxx/utils/google-benchmark/src/mutex.h | |
| parent | 2d23c029f75e3991381297695c4c085fec9c6833 (diff) | |
| download | bcm5719-llvm-b08d8b189c0a3a7c92242836767383721ad7e89d.tar.gz bcm5719-llvm-b08d8b189c0a3a7c92242836767383721ad7e89d.zip | |
[libcxx] Add support for benchmark tests using Google Benchmark.
Summary:
This patch does the following:
1. Checks in a copy of the Google Benchmark library into the libc++ repo under `utils/google-benchmark`.
2. Teaches libc++ how to build Google Benchmark against both (A) in-tree libc++ and (B) the platforms native STL.
3. Allows performance benchmarks to be built as part of the libc++ build.
Building the benchmarks (and Google Benchmark) is off by default. It must be enabled using the CMake option `-DLIBCXX_INCLUDE_BENCHMARKS=ON`. When this option is enabled the tests under `libcxx/benchmarks` can be built using the `libcxx-benchmarks` target.
On Linux platforms where libstdc++ is the default STL the CMake option `-DLIBCXX_BUILD_BENCHMARKS_NATIVE_STDLIB=ON` can be used to build each benchmark test against libstdc++ as well. This is useful for comparing performance between standard libraries.
Support for benchmarks is currently very minimal. They must be manually run by the user and there is no mechanism for detecting performance regressions.
Known Issues:
* `-DLIBCXX_INCLUDE_BENCHMARKS=ON` is only supported for Clang, and not GCC, since the `-stdlib=libc++` option is needed to build Google Benchmark.
Reviewers: danalbert, dberlin, chandlerc, mclow.lists, jroelofs
Subscribers: chandlerc, dberlin, tberghammer, danalbert, srhines, hfinkel
Differential Revision: https://reviews.llvm.org/D22240
llvm-svn: 276049
Diffstat (limited to 'libcxx/utils/google-benchmark/src/mutex.h')
| -rw-r--r-- | libcxx/utils/google-benchmark/src/mutex.h | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/libcxx/utils/google-benchmark/src/mutex.h b/libcxx/utils/google-benchmark/src/mutex.h new file mode 100644 index 00000000000..f37ec35b3a4 --- /dev/null +++ b/libcxx/utils/google-benchmark/src/mutex.h @@ -0,0 +1,142 @@ +#ifndef BENCHMARK_MUTEX_H_ +#define BENCHMARK_MUTEX_H_ + +#include <mutex> +#include <condition_variable> + +// Enable thread safety attributes only with clang. +// The attributes can be safely erased when compiling with other compilers. +#if defined(HAVE_THREAD_SAFETY_ATTRIBUTES) +#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) +#else +#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op +#endif + +#define CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) + +#define SCOPED_CAPABILITY \ + THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) + +#define GUARDED_BY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) + +#define PT_GUARDED_BY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) + +#define ACQUIRED_BEFORE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) + +#define ACQUIRED_AFTER(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) + +#define REQUIRES(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) + +#define REQUIRES_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) + +#define ACQUIRE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) + +#define ACQUIRE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) + +#define RELEASE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) + +#define RELEASE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) + +#define TRY_ACQUIRE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) + +#define TRY_ACQUIRE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) + +#define EXCLUDES(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) + +#define ASSERT_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) + +#define ASSERT_SHARED_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) + +#define RETURN_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) + +#define NO_THREAD_SAFETY_ANALYSIS \ + THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) + + +namespace benchmark { + +typedef std::condition_variable Condition; + +// NOTE: Wrappers for std::mutex and std::unique_lock are provided so that +// we can annotate them with thread safety attributes and use the +// -Wthread-safety warning with clang. The standard library types cannot be +// used directly because they do not provided the required annotations. +class CAPABILITY("mutex") Mutex +{ +public: + Mutex() {} + + void lock() ACQUIRE() { mut_.lock(); } + void unlock() RELEASE() { mut_.unlock(); } + std::mutex& native_handle() { + return mut_; + } +private: + std::mutex mut_; +}; + + +class SCOPED_CAPABILITY MutexLock +{ + typedef std::unique_lock<std::mutex> MutexLockImp; +public: + MutexLock(Mutex& m) ACQUIRE(m) : ml_(m.native_handle()) + { } + ~MutexLock() RELEASE() {} + MutexLockImp& native_handle() { return ml_; } +private: + MutexLockImp ml_; +}; + + +class Notification +{ +public: + Notification() : notified_yet_(false) { } + + void WaitForNotification() const EXCLUDES(mutex_) { + MutexLock m_lock(mutex_); + auto notified_fn = [this]() REQUIRES(mutex_) { + return this->HasBeenNotified(); + }; + cv_.wait(m_lock.native_handle(), notified_fn); + } + + void Notify() EXCLUDES(mutex_) { + { + MutexLock lock(mutex_); + notified_yet_ = 1; + } + cv_.notify_all(); + } + +private: + bool HasBeenNotified() const REQUIRES(mutex_) { + return notified_yet_; + } + + mutable Mutex mutex_; + mutable std::condition_variable cv_; + bool notified_yet_ GUARDED_BY(mutex_); +}; + +} // end namespace benchmark + +#endif // BENCHMARK_MUTEX_H_ |

