tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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