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