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 "mozilla/RecursiveMutex.h"
8 
9 #ifdef XP_WIN
10 #  include <windows.h>
11 
12 #  define NativeHandle(m) (reinterpret_cast<CRITICAL_SECTION*>(&m))
13 #endif
14 
15 namespace mozilla {
16 
RecursiveMutex(const char * aName)17 RecursiveMutex::RecursiveMutex(const char* aName)
18     : BlockingResourceBase(aName, eRecursiveMutex)
19 #ifdef DEBUG
20       ,
21       mOwningThread(nullptr),
22       mEntryCount(0)
23 #endif
24 {
25 #ifdef XP_WIN
26   // This number was adapted from NSPR.
27   static const DWORD sLockSpinCount = 100;
28 
29 #  if defined(RELEASE_OR_BETA)
30   // Vista and later automatically allocate and subsequently leak a debug info
31   // object for each critical section that we allocate unless we tell the
32   // system not to do that.
33   DWORD flags = CRITICAL_SECTION_NO_DEBUG_INFO;
34 #  else
35   DWORD flags = 0;
36 #  endif
37   BOOL r =
38       InitializeCriticalSectionEx(NativeHandle(mMutex), sLockSpinCount, flags);
39   MOZ_RELEASE_ASSERT(r);
40 #else
41   pthread_mutexattr_t attr;
42 
43   MOZ_RELEASE_ASSERT(pthread_mutexattr_init(&attr) == 0,
44                      "pthread_mutexattr_init failed");
45 
46   MOZ_RELEASE_ASSERT(
47       pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) == 0,
48       "pthread_mutexattr_settype failed");
49 
50   MOZ_RELEASE_ASSERT(pthread_mutex_init(&mMutex, &attr) == 0,
51                      "pthread_mutex_init failed");
52 
53   MOZ_RELEASE_ASSERT(pthread_mutexattr_destroy(&attr) == 0,
54                      "pthread_mutexattr_destroy failed");
55 #endif
56 }
57 
~RecursiveMutex()58 RecursiveMutex::~RecursiveMutex() {
59 #ifdef XP_WIN
60   DeleteCriticalSection(NativeHandle(mMutex));
61 #else
62   MOZ_RELEASE_ASSERT(pthread_mutex_destroy(&mMutex) == 0,
63                      "pthread_mutex_destroy failed");
64 #endif
65 }
66 
LockInternal()67 void RecursiveMutex::LockInternal() {
68 #ifdef XP_WIN
69   EnterCriticalSection(NativeHandle(mMutex));
70 #else
71   MOZ_RELEASE_ASSERT(pthread_mutex_lock(&mMutex) == 0,
72                      "pthread_mutex_lock failed");
73 #endif
74 }
75 
UnlockInternal()76 void RecursiveMutex::UnlockInternal() {
77 #ifdef XP_WIN
78   LeaveCriticalSection(NativeHandle(mMutex));
79 #else
80   MOZ_RELEASE_ASSERT(pthread_mutex_unlock(&mMutex) == 0,
81                      "pthread_mutex_unlock failed");
82 #endif
83 }
84 
85 }  // namespace mozilla
86