-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
common/ceph_mutex: ceph::{mutex,condition_variable,lock_guard}
If CEPH_DEBUG_MUTEX is defined, use the [recursive_]mutex_debug classes that implement lockdep and a bucnh of other random debug checks. Also typedef ceph::condition_variable to std::condition_variable_debug, which adds addition assertions and debug checks. If CEPH_DEBUG_MUTEX is not defined, then use the bare-bones C++ std::mutex primitives... or as close as we can get to them. Since the [recursive_]mutex_debug classes take a string argument for the lockdep piece, define factory functions ceph::make_[recursive_]mutex that either pass arguments to the debug implementations or toss them out. Signed-off-by: Sage Weil <[email protected]>
- Loading branch information
Showing
6 changed files
with
164 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- | ||
// vim: ts=8 sw=2 smarttab | ||
|
||
#pragma once | ||
|
||
// What and why | ||
// ============ | ||
// | ||
// For general code making use of mutexes, use these ceph:: types. | ||
// The key requirement is that you make use of the ceph::make_mutex() | ||
// and make_recursive_mutex() factory methods, which take a string | ||
// naming the mutex for the purposes of the lockdep debug variant. | ||
// | ||
// For legacy Mutex users that passed recursive=true, use | ||
// ceph::make_recursive_mutex. For legacy Mutex users that passed | ||
// lockdep=false, use std::mutex directly. | ||
|
||
#ifdef CEPH_DEBUG_MUTEX | ||
|
||
// ============================================================================ | ||
// debug (lockdep-capable, various sanity checks and asserts) | ||
// ============================================================================ | ||
|
||
#include "common/mutex_debug.h" | ||
#include "common/condition_variable_debug.h" | ||
|
||
namespace ceph { | ||
typedef ceph::mutex_debug mutex; | ||
typedef ceph::mutex_recursive_debug recursive_mutex; | ||
typedef ceph::condition_variable_debug condition_variable; | ||
|
||
// pass arguments to mutex_debug ctor | ||
template <typename ...Args> | ||
mutex make_mutex(Args&& ...args) { | ||
return {std::forward<Args>(args)...}; | ||
} | ||
|
||
// pass arguments to recursive_mutex_debug ctor | ||
template <typename ...Args> | ||
recursive_mutex make_recursive_mutex(Args&& ...args) { | ||
return {std::forward<Args>(args)...}; | ||
} | ||
|
||
// debug methods | ||
#define ceph_mutex_is_locked(m) ((m).is_locked()) | ||
#define ceph_mutex_is_locked_by_me(m) ((m).is_locked_by_me()) | ||
} | ||
|
||
#else | ||
|
||
// ============================================================================ | ||
// release (fast and minimal) | ||
// ============================================================================ | ||
|
||
#include <mutex> | ||
#include <condition_variable> | ||
|
||
namespace ceph { | ||
|
||
typedef std::mutex mutex; | ||
typedef std::recursive_mutex recursive_mutex; | ||
typedef std::condition_variable condition_variable; | ||
|
||
// discard arguments to make_mutex (they are for debugging only) | ||
template <typename ...Args> | ||
std::mutex make_mutex(Args&& ...args) { | ||
return {}; | ||
} | ||
template <typename ...Args> | ||
std::recursive_mutex make_recursive_mutex(Args&& ...args) { | ||
return {}; | ||
} | ||
|
||
// debug methods. Note that these can blindly return true | ||
// because any code that does anything other than assert these | ||
// are true is broken. | ||
#define ceph_mutex_is_locked(m) true | ||
#define ceph_mutex_is_locked_by_me(m) true | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- | ||
// vim: ts=8 sw=2 smarttab | ||
|
||
#include "common/ceph_context.h" | ||
#include "include/util.h" | ||
#include "gtest/gtest.h" | ||
#include "common/ceph_mutex.h" | ||
#include "global/global_context.h" | ||
#include "global/global_init.h" | ||
|
||
TEST(lockdep, abba) | ||
{ | ||
ASSERT_TRUE(g_lockdep); | ||
|
||
ceph::mutex a(ceph::make_mutex("a")), b(ceph::make_mutex("b")); | ||
a.lock(); | ||
ASSERT_TRUE(ceph_mutex_is_locked(a)); | ||
ASSERT_TRUE(ceph_mutex_is_locked_by_me(a)); | ||
b.lock(); | ||
ASSERT_TRUE(ceph_mutex_is_locked(b)); | ||
ASSERT_TRUE(ceph_mutex_is_locked_by_me(b)); | ||
a.unlock(); | ||
b.unlock(); | ||
|
||
b.lock(); | ||
EXPECT_DEATH(a.lock(), ""); | ||
b.unlock(); | ||
} | ||
|
||
TEST(lockdep, recursive) | ||
{ | ||
ASSERT_TRUE(g_lockdep); | ||
|
||
ceph::mutex a(ceph::make_mutex("a")); | ||
a.lock(); | ||
EXPECT_DEATH(a.lock(), ""); | ||
a.unlock(); | ||
|
||
ceph::recursive_mutex b(ceph::make_recursive_mutex("b")); | ||
b.lock(); | ||
ASSERT_TRUE(ceph_mutex_is_locked(b)); | ||
ASSERT_TRUE(ceph_mutex_is_locked_by_me(b)); | ||
b.lock(); | ||
b.unlock(); | ||
b.unlock(); | ||
} | ||
|
||
int main(int argc, char **argv) { | ||
#ifdef NDEBUG | ||
cout << "NDEBUG is defined" << std::endl; | ||
#else | ||
cout << "NDEBUG is NOT defined" << std::endl; | ||
#endif | ||
#ifndef CEPH_DEBUG_MUTEX | ||
cerr << "WARNING: CEPH_DEBUG_MUTEX is not defined, lockdep will not work" | ||
<< std::endl; | ||
exit(0); | ||
#endif | ||
std::vector<const char*> args(argv, argv + argc); | ||
args.push_back("--lockdep"); | ||
auto cct = global_init(NULL, args, | ||
CEPH_ENTITY_TYPE_CLIENT, | ||
CODE_ENVIRONMENT_UTILITY, | ||
CINIT_FLAG_NO_MON_CONFIG); | ||
common_init_finish(g_ceph_context); | ||
|
||
::testing::InitGoogleTest(&argc, argv); | ||
return RUN_ALL_TESTS(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters