GCLock.h (2673B)
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 /* 8 * GC-internal classes for acquiring and releasing the GC lock. 9 */ 10 11 #ifndef gc_GCLock_h 12 #define gc_GCLock_h 13 14 #include "vm/Runtime.h" 15 16 namespace js { 17 18 /* 19 * RAII class that takes the GC lock while it is live. 20 * 21 * Usually functions will pass const references of this class. However 22 * non-const references can be used to either temporarily release the lock by 23 * use of AutoUnlockGC or to start background allocation when the lock is 24 * released. 25 */ 26 class MOZ_RAII AutoLockGC { 27 public: 28 explicit AutoLockGC(gc::GCRuntime* gc) : gc(gc) { lock(); } 29 explicit AutoLockGC(JSRuntime* rt) : AutoLockGC(&rt->gc) {} 30 31 ~AutoLockGC() { lockGuard_.reset(); } 32 33 LockGuard<Mutex>& guard() { return lockGuard_.ref(); } 34 35 protected: 36 void lock() { 37 MOZ_ASSERT(lockGuard_.isNothing()); 38 lockGuard_.emplace(gc->lock); 39 } 40 41 void unlock() { 42 MOZ_ASSERT(lockGuard_.isSome()); 43 lockGuard_.reset(); 44 } 45 46 gc::GCRuntime* const gc; 47 48 private: 49 mozilla::Maybe<LockGuard<Mutex>> lockGuard_; 50 51 AutoLockGC(const AutoLockGC&) = delete; 52 AutoLockGC& operator=(const AutoLockGC&) = delete; 53 54 friend class UnlockGuard<AutoLockGC>; // For lock/unlock. 55 }; 56 57 /* 58 * Same as AutoLockGC except it can optionally start a background chunk 59 * allocation task when the lock is released. 60 */ 61 class MOZ_RAII AutoLockGCBgAlloc : public AutoLockGC { 62 public: 63 explicit AutoLockGCBgAlloc(gc::GCRuntime* gc) : AutoLockGC(gc) {} 64 explicit AutoLockGCBgAlloc(JSRuntime* rt) : AutoLockGCBgAlloc(&rt->gc) {} 65 66 ~AutoLockGCBgAlloc() { 67 unlock(); 68 69 /* 70 * We have to do this after releasing the lock because it may acquire 71 * the helper lock which could cause lock inversion if we still held 72 * the GC lock. 73 */ 74 if (startBgAlloc) { 75 gc->startBackgroundAllocTaskIfIdle(); 76 } 77 } 78 79 /* 80 * This can be used to start a background allocation task (if one isn't 81 * already running) that allocates chunks and makes them available in the 82 * free chunks list. This happens after the lock is released in order to 83 * avoid lock inversion. 84 */ 85 void tryToStartBackgroundAllocation() { startBgAlloc = true; } 86 87 private: 88 // true if we should start a background chunk allocation task after the 89 // lock is released. 90 bool startBgAlloc = false; 91 }; 92 93 using AutoUnlockGC = UnlockGuard<AutoLockGC>; 94 95 } // namespace js 96 97 #endif /* gc_GCLock_h */