| 150 | |
| 151 | template <typename MutexType> |
| 152 | static void push_lock(MutexType* c, const CLockLocation& locklocation) |
| 153 | { |
| 154 | constexpr bool is_recursive_mutex = |
| 155 | std::is_base_of<RecursiveMutex, MutexType>::value || |
| 156 | std::is_base_of<std::recursive_mutex, MutexType>::value; |
| 157 | |
| 158 | LockData& lockdata = GetLockData(); |
| 159 | std::lock_guard<std::mutex> lock(lockdata.dd_mutex); |
| 160 | |
| 161 | LockStack& lock_stack = lockdata.m_lock_stacks[std::this_thread::get_id()]; |
| 162 | lock_stack.emplace_back(c, locklocation); |
| 163 | for (size_t j = 0; j < lock_stack.size() - 1; ++j) { |
| 164 | const LockStackItem& i = lock_stack[j]; |
| 165 | if (i.first == c) { |
| 166 | if (is_recursive_mutex) { |
| 167 | break; |
| 168 | } |
| 169 | // It is not a recursive mutex and it appears in the stack two times: |
| 170 | // at position `j` and at the end (which we added just before this loop). |
| 171 | // Can't allow locking the same (non-recursive) mutex two times from the |
| 172 | // same thread as that results in an undefined behavior. |
| 173 | auto lock_stack_copy = lock_stack; |
| 174 | lock_stack.pop_back(); |
| 175 | double_lock_detected(c, lock_stack_copy); |
| 176 | // double_lock_detected() does not return. |
| 177 | } |
| 178 | |
| 179 | const LockPair p1 = std::make_pair(i.first, c); |
| 180 | if (lockdata.lockorders.count(p1)) |
| 181 | continue; |
| 182 | |
| 183 | const LockPair p2 = std::make_pair(c, i.first); |
| 184 | if (lockdata.lockorders.count(p2)) { |
| 185 | auto lock_stack_copy = lock_stack; |
| 186 | lock_stack.pop_back(); |
| 187 | potential_deadlock_detected(p1, lockdata.lockorders[p2], lock_stack_copy); |
| 188 | // potential_deadlock_detected() does not return. |
| 189 | } |
| 190 | |
| 191 | lockdata.lockorders.emplace(p1, lock_stack); |
| 192 | lockdata.invlockorders.insert(p2); |
| 193 | } |
| 194 | } |
| 195 | |
| 196 | static void pop_lock() |
| 197 | { |
no test coverage detected