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/. */
12 #elif defined(XP_DARWIN)
13 # include <libkern/OSAtomic.h>
17 #include "mozilla/Attributes.h"
18 #include "mozilla/GuardObjects.h"
20 // Mutexes based on spinlocks. We can't use normal pthread spinlocks in all
21 // places, because they require malloc()ed memory, which causes bootstrapping
22 // issues in some cases. We also can't use constructors, because for statics,
23 // they would fire after the first use of malloc, resetting the locks.
26 CRITICAL_SECTION mMutex
;
27 #elif defined(XP_DARWIN)
30 pthread_mutex_t mMutex
;
33 // Initializes a mutex. Returns whether initialization succeeded.
36 if (!InitializeCriticalSectionAndSpinCount(&mMutex
, 5000)) {
39 #elif defined(XP_DARWIN)
40 mMutex
= OS_SPINLOCK_INIT
;
41 #elif defined(XP_LINUX) && !defined(ANDROID)
42 pthread_mutexattr_t attr
;
43 if (pthread_mutexattr_init(&attr
) != 0) {
46 pthread_mutexattr_settype(&attr
, PTHREAD_MUTEX_ADAPTIVE_NP
);
47 if (pthread_mutex_init(&mMutex
, &attr
) != 0) {
48 pthread_mutexattr_destroy(&attr
);
51 pthread_mutexattr_destroy(&attr
);
53 if (pthread_mutex_init(&mMutex
, nullptr) != 0) {
62 EnterCriticalSection(&mMutex
);
63 #elif defined(XP_DARWIN)
64 OSSpinLockLock(&mMutex
);
66 pthread_mutex_lock(&mMutex
);
70 inline void Unlock() {
72 LeaveCriticalSection(&mMutex
);
73 #elif defined(XP_DARWIN)
74 OSSpinLockUnlock(&mMutex
);
76 pthread_mutex_unlock(&mMutex
);
81 // Mutex that can be used for static initialization.
82 // On Windows, CRITICAL_SECTION requires a function call to be initialized,
83 // but for the initialization lock, a static initializer calling the
84 // function would be called too late. We need no-function-call
85 // initialization, which SRWLock provides.
86 // Ideally, we'd use the same type of locks everywhere, but SRWLocks
87 // everywhere incur a performance penalty. See bug 1418389.
92 inline void Lock() { AcquireSRWLockExclusive(&mMutex
); }
94 inline void Unlock() { ReleaseSRWLockExclusive(&mMutex
); }
97 // Normally, we'd use a constexpr constructor, but MSVC likes to create
98 // static initializers anyways.
99 # define STATIC_MUTEX_INIT SRWLOCK_INIT
102 typedef Mutex StaticMutex
;
104 # if defined(XP_DARWIN)
105 # define STATIC_MUTEX_INIT OS_SPINLOCK_INIT
106 # elif defined(XP_LINUX) && !defined(ANDROID)
107 # define STATIC_MUTEX_INIT PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
109 # define STATIC_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
114 template <typename T
>
115 struct MOZ_RAII AutoLock
{
116 explicit AutoLock(T
& aMutex MOZ_GUARD_OBJECT_NOTIFIER_PARAM
)
118 MOZ_GUARD_OBJECT_NOTIFIER_INIT
;
122 ~AutoLock() { mMutex
.Unlock(); }
125 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
;
129 using MutexAutoLock
= AutoLock
<Mutex
>;