Mutex.cpp (2120B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "threading/Mutex.h" 8 9 using namespace js; 10 11 #ifdef DEBUG 12 13 MOZ_THREAD_LOCAL(js::Mutex*) js::Mutex::HeldMutexStack; 14 15 /* static */ 16 bool js::Mutex::Init() { return HeldMutexStack.init(); } 17 18 void js::Mutex::lock() { 19 preLockChecks(); 20 impl_.lock(); 21 postLockChecks(); 22 } 23 24 bool js::Mutex::tryLock() { 25 preLockChecks(); 26 if (!impl_.tryLock()) { 27 return false; 28 } 29 30 postLockChecks(); 31 return true; 32 } 33 34 void js::Mutex::preLockChecks() const { 35 Mutex* prev = HeldMutexStack.get(); 36 if (prev) { 37 if (id_.order <= prev->id_.order) { 38 fprintf(stderr, 39 "Attempt to acquire mutex %s with order %u while holding %s with " 40 "order %u\n", 41 id_.name, id_.order, prev->id_.name, prev->id_.order); 42 MOZ_CRASH("Mutex ordering violation"); 43 } 44 } 45 } 46 47 void js::Mutex::postLockChecks() { 48 MOZ_ASSERT(!owningThread_); 49 owningThread_ = ThreadId::ThisThreadId(); 50 51 MOZ_ASSERT(prev_ == nullptr); 52 prev_ = HeldMutexStack.get(); 53 HeldMutexStack.set(this); 54 } 55 56 void js::Mutex::unlock() { 57 preUnlockChecks(); 58 impl_.unlock(); 59 } 60 61 void js::Mutex::preUnlockChecks() { 62 Mutex* stack = HeldMutexStack.get(); 63 MOZ_ASSERT(stack == this); 64 HeldMutexStack.set(prev_); 65 prev_ = nullptr; 66 67 MOZ_ASSERT(ThreadId::ThisThreadId() == owningThread_); 68 owningThread_ = ThreadId(); 69 } 70 71 void js::Mutex::assertOwnedByCurrentThread() const { 72 // This check is only thread-safe if it succeeds. 73 MOZ_ASSERT(ThreadId::ThisThreadId() == owningThread_); 74 75 MOZ_ASSERT(isOwnedByCurrentThread()); 76 } 77 78 bool js::Mutex::isOwnedByCurrentThread() const { 79 // Check whether the mutex is on the thread-local mutex stack. 80 for (Mutex* mutex = HeldMutexStack.get(); mutex; mutex = mutex->prev_) { 81 if (mutex == this) { 82 return true; 83 } 84 } 85 86 return false; 87 } 88 89 #endif