1 // Copyright 2020 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_HEAP_PARKED_SCOPE_H_ 6 #define V8_HEAP_PARKED_SCOPE_H_ 7 8 #include "src/base/platform/mutex.h" 9 #include "src/execution/local-isolate.h" 10 #include "src/heap/local-heap.h" 11 12 namespace v8 { 13 namespace internal { 14 15 // Scope that explicitly parks a thread, prohibiting access to the heap and the 16 // creation of handles. 17 class V8_NODISCARD ParkedScope { 18 public: ParkedScope(LocalIsolate * local_isolate)19 explicit ParkedScope(LocalIsolate* local_isolate) 20 : ParkedScope(local_isolate->heap()) {} ParkedScope(LocalHeap * local_heap)21 explicit ParkedScope(LocalHeap* local_heap) : local_heap_(local_heap) { 22 local_heap_->Park(); 23 } 24 ~ParkedScope()25 ~ParkedScope() { local_heap_->Unpark(); } 26 27 private: 28 LocalHeap* const local_heap_; 29 }; 30 31 // Scope that explicitly unparks a thread, allowing access to the heap and the 32 // creation of handles. 33 class V8_NODISCARD UnparkedScope { 34 public: UnparkedScope(LocalIsolate * local_isolate)35 explicit UnparkedScope(LocalIsolate* local_isolate) 36 : UnparkedScope(local_isolate->heap()) {} UnparkedScope(LocalHeap * local_heap)37 explicit UnparkedScope(LocalHeap* local_heap) : local_heap_(local_heap) { 38 local_heap_->Unpark(); 39 } 40 ~UnparkedScope()41 ~UnparkedScope() { local_heap_->Park(); } 42 43 private: 44 LocalHeap* const local_heap_; 45 }; 46 47 class V8_NODISCARD ParkedMutexGuard { 48 public: ParkedMutexGuard(LocalIsolate * local_isolate,base::Mutex * mutex)49 explicit ParkedMutexGuard(LocalIsolate* local_isolate, base::Mutex* mutex) 50 : ParkedMutexGuard(local_isolate->heap(), mutex) {} ParkedMutexGuard(LocalHeap * local_heap,base::Mutex * mutex)51 explicit ParkedMutexGuard(LocalHeap* local_heap, base::Mutex* mutex) 52 : mutex_(mutex) { 53 DCHECK(AllowGarbageCollection::IsAllowed()); 54 if (!mutex_->TryLock()) { 55 ParkedScope scope(local_heap); 56 mutex_->Lock(); 57 } 58 } 59 60 ParkedMutexGuard(const ParkedMutexGuard&) = delete; 61 ParkedMutexGuard& operator=(const ParkedMutexGuard&) = delete; 62 ~ParkedMutexGuard()63 ~ParkedMutexGuard() { mutex_->Unlock(); } 64 65 private: 66 base::Mutex* mutex_; 67 }; 68 69 template <base::MutexSharedType kIsShared, 70 base::NullBehavior Behavior = base::NullBehavior::kRequireNotNull> 71 class V8_NODISCARD ParkedSharedMutexGuardIf final { 72 public: ParkedSharedMutexGuardIf(LocalIsolate * local_isolate,base::SharedMutex * mutex,bool enable_mutex)73 ParkedSharedMutexGuardIf(LocalIsolate* local_isolate, 74 base::SharedMutex* mutex, bool enable_mutex) 75 : ParkedSharedMutexGuardIf(local_isolate->heap(), mutex, enable_mutex) {} ParkedSharedMutexGuardIf(LocalHeap * local_heap,base::SharedMutex * mutex,bool enable_mutex)76 ParkedSharedMutexGuardIf(LocalHeap* local_heap, base::SharedMutex* mutex, 77 bool enable_mutex) { 78 DCHECK(AllowGarbageCollection::IsAllowed()); 79 DCHECK_IMPLIES(Behavior == base::NullBehavior::kRequireNotNull, 80 mutex != nullptr); 81 if (!enable_mutex) return; 82 mutex_ = mutex; 83 84 if (kIsShared) { 85 if (!mutex_->TryLockShared()) { 86 ParkedScope scope(local_heap); 87 mutex_->LockShared(); 88 } 89 } else { 90 if (!mutex_->TryLockExclusive()) { 91 ParkedScope scope(local_heap); 92 mutex_->LockExclusive(); 93 } 94 } 95 } 96 ParkedSharedMutexGuardIf(const ParkedSharedMutexGuardIf&) = delete; 97 ParkedSharedMutexGuardIf& operator=(const ParkedSharedMutexGuardIf&) = delete; 98 ~ParkedSharedMutexGuardIf()99 ~ParkedSharedMutexGuardIf() { 100 if (!mutex_) return; 101 102 if (kIsShared) { 103 mutex_->UnlockShared(); 104 } else { 105 mutex_->UnlockExclusive(); 106 } 107 } 108 109 private: 110 base::SharedMutex* mutex_ = nullptr; 111 }; 112 113 } // namespace internal 114 } // namespace v8 115 116 #endif // V8_HEAP_PARKED_SCOPE_H_ 117