Bug 1651162 [wpt PR 24490] - Origin isolation: add WPTs for different ports, a=testonly
[gecko.git] / memory / build / Mutex.h
blobf871cf9d82890a69d3c343954ea52627ad56d648
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/. */
7 #ifndef Mutex_h
8 #define Mutex_h
10 #if defined(XP_WIN)
11 # include <windows.h>
12 #elif defined(XP_DARWIN)
13 # include <libkern/OSAtomic.h>
14 #else
15 # include <pthread.h>
16 #endif
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.
24 struct Mutex {
25 #if defined(XP_WIN)
26 CRITICAL_SECTION mMutex;
27 #elif defined(XP_DARWIN)
28 OSSpinLock mMutex;
29 #else
30 pthread_mutex_t mMutex;
31 #endif
33 // Initializes a mutex. Returns whether initialization succeeded.
34 inline bool Init() {
35 #if defined(XP_WIN)
36 if (!InitializeCriticalSectionAndSpinCount(&mMutex, 5000)) {
37 return false;
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) {
44 return false;
46 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);
47 if (pthread_mutex_init(&mMutex, &attr) != 0) {
48 pthread_mutexattr_destroy(&attr);
49 return false;
51 pthread_mutexattr_destroy(&attr);
52 #else
53 if (pthread_mutex_init(&mMutex, nullptr) != 0) {
54 return false;
56 #endif
57 return true;
60 inline void Lock() {
61 #if defined(XP_WIN)
62 EnterCriticalSection(&mMutex);
63 #elif defined(XP_DARWIN)
64 OSSpinLockLock(&mMutex);
65 #else
66 pthread_mutex_lock(&mMutex);
67 #endif
70 inline void Unlock() {
71 #if defined(XP_WIN)
72 LeaveCriticalSection(&mMutex);
73 #elif defined(XP_DARWIN)
74 OSSpinLockUnlock(&mMutex);
75 #else
76 pthread_mutex_unlock(&mMutex);
77 #endif
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.
88 #if defined(XP_WIN)
89 struct StaticMutex {
90 SRWLOCK mMutex;
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
101 #else
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
108 # else
109 # define STATIC_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
110 # endif
112 #endif
114 template <typename T>
115 struct MOZ_RAII AutoLock {
116 explicit AutoLock(T& aMutex MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
117 : mMutex(aMutex) {
118 MOZ_GUARD_OBJECT_NOTIFIER_INIT;
119 mMutex.Lock();
122 ~AutoLock() { mMutex.Unlock(); }
124 private:
125 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
126 T& mMutex;
129 using MutexAutoLock = AutoLock<Mutex>;
131 #endif