tor-browser

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

WinUtils.h (4043B)


      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 #ifndef mozilla_glue_MozglueUtils_h
      8 #define mozilla_glue_MozglueUtils_h
      9 
     10 #include <windows.h>
     11 
     12 #include "mozilla/Atomics.h"
     13 #include "mozilla/Attributes.h"
     14 
     15 namespace mozilla {
     16 namespace glue {
     17 
     18 #ifdef DEBUG
     19 
     20 class MOZ_STATIC_CLASS Win32SRWLock final {
     21 public:
     22  // Microsoft guarantees that '0' is never a valid thread id
     23  // https://docs.microsoft.com/en-ca/windows/desktop/ProcThread/thread-handles-and-identifiers
     24  static const DWORD kInvalidThreadId = 0;
     25 
     26  constexpr Win32SRWLock()
     27      : mExclusiveThreadId(kInvalidThreadId), mLock(SRWLOCK_INIT) {}
     28 
     29  ~Win32SRWLock() { MOZ_ASSERT(mExclusiveThreadId == kInvalidThreadId); }
     30 
     31  void LockShared() {
     32    MOZ_ASSERT(
     33        mExclusiveThreadId != GetCurrentThreadId(),
     34        "Deadlock detected - A thread attempted to acquire a shared lock on "
     35        "a SRWLOCK when it already owns the exclusive lock on it.");
     36 
     37    ::AcquireSRWLockShared(&mLock);
     38  }
     39 
     40  void UnlockShared() { ::ReleaseSRWLockShared(&mLock); }
     41 
     42  void LockExclusive() {
     43    MOZ_ASSERT(
     44        mExclusiveThreadId != GetCurrentThreadId(),
     45        "Deadlock detected - A thread attempted to acquire an exclusive lock "
     46        "on a SRWLOCK when it already owns the exclusive lock on it.");
     47 
     48    ::AcquireSRWLockExclusive(&mLock);
     49    mExclusiveThreadId = GetCurrentThreadId();
     50  }
     51 
     52  void UnlockExclusive() {
     53    MOZ_ASSERT(mExclusiveThreadId == GetCurrentThreadId());
     54 
     55    mExclusiveThreadId = kInvalidThreadId;
     56    ::ReleaseSRWLockExclusive(&mLock);
     57  }
     58 
     59  Win32SRWLock(const Win32SRWLock&) = delete;
     60  Win32SRWLock(Win32SRWLock&&) = delete;
     61  Win32SRWLock& operator=(const Win32SRWLock&) = delete;
     62  Win32SRWLock& operator=(Win32SRWLock&&) = delete;
     63 
     64 private:
     65  // "Relaxed" memory ordering is fine. Threads will see other thread IDs
     66  // appear here in some non-deterministic ordering (or not at all) and simply
     67  // ignore them.
     68  //
     69  // But a thread will only read its own ID if it previously wrote it, and a
     70  // single thread doesn't need a memory barrier to read its own write.
     71 
     72  Atomic<DWORD, Relaxed> mExclusiveThreadId;
     73  SRWLOCK mLock;
     74 };
     75 
     76 #else  // DEBUG
     77 
     78 class MOZ_STATIC_CLASS Win32SRWLock final {
     79 public:
     80  constexpr Win32SRWLock() : mLock(SRWLOCK_INIT) {}
     81 
     82  void LockShared() { ::AcquireSRWLockShared(&mLock); }
     83 
     84  void UnlockShared() { ::ReleaseSRWLockShared(&mLock); }
     85 
     86  void LockExclusive() { ::AcquireSRWLockExclusive(&mLock); }
     87 
     88  void UnlockExclusive() { ::ReleaseSRWLockExclusive(&mLock); }
     89 
     90  ~Win32SRWLock() = default;
     91 
     92  Win32SRWLock(const Win32SRWLock&) = delete;
     93  Win32SRWLock(Win32SRWLock&&) = delete;
     94  Win32SRWLock& operator=(const Win32SRWLock&) = delete;
     95  Win32SRWLock& operator=(Win32SRWLock&&) = delete;
     96 
     97 private:
     98  SRWLOCK mLock;
     99 };
    100 
    101 #endif
    102 
    103 class MOZ_RAII AutoSharedLock final {
    104 public:
    105  explicit AutoSharedLock(Win32SRWLock& aLock) : mLock(aLock) {
    106    mLock.LockShared();
    107  }
    108 
    109  ~AutoSharedLock() { mLock.UnlockShared(); }
    110 
    111  AutoSharedLock(const AutoSharedLock&) = delete;
    112  AutoSharedLock(AutoSharedLock&&) = delete;
    113  AutoSharedLock& operator=(const AutoSharedLock&) = delete;
    114  AutoSharedLock& operator=(AutoSharedLock&&) = delete;
    115 
    116 private:
    117  Win32SRWLock& mLock;
    118 };
    119 
    120 class MOZ_RAII AutoExclusiveLock final {
    121 public:
    122  explicit AutoExclusiveLock(Win32SRWLock& aLock) : mLock(aLock) {
    123    mLock.LockExclusive();
    124  }
    125 
    126  ~AutoExclusiveLock() { mLock.UnlockExclusive(); }
    127 
    128  AutoExclusiveLock(const AutoExclusiveLock&) = delete;
    129  AutoExclusiveLock(AutoExclusiveLock&&) = delete;
    130  AutoExclusiveLock& operator=(const AutoExclusiveLock&) = delete;
    131  AutoExclusiveLock& operator=(AutoExclusiveLock&&) = delete;
    132 
    133 private:
    134  Win32SRWLock& mLock;
    135 };
    136 
    137 }  // namespace glue
    138 }  // namespace mozilla
    139 
    140 #endif  //  mozilla_glue_MozglueUtils_h