• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // Scope that automatically parks the thread while blocking on the given
48 // base::Mutex.
49 class V8_NODISCARD ParkedMutexGuard {
50  public:
ParkedMutexGuard(LocalIsolate * local_isolate,base::Mutex * mutex)51   explicit ParkedMutexGuard(LocalIsolate* local_isolate, base::Mutex* mutex)
52       : ParkedMutexGuard(local_isolate->heap(), mutex) {}
ParkedMutexGuard(LocalHeap * local_heap,base::Mutex * mutex)53   explicit ParkedMutexGuard(LocalHeap* local_heap, base::Mutex* mutex)
54       : mutex_(mutex) {
55     DCHECK(AllowGarbageCollection::IsAllowed());
56     if (!mutex_->TryLock()) {
57       ParkedScope scope(local_heap);
58       mutex_->Lock();
59     }
60   }
61 
62   ParkedMutexGuard(const ParkedMutexGuard&) = delete;
63   ParkedMutexGuard& operator=(const ParkedMutexGuard&) = delete;
64 
~ParkedMutexGuard()65   ~ParkedMutexGuard() { mutex_->Unlock(); }
66 
67  private:
68   base::Mutex* mutex_;
69 };
70 
71 template <base::MutexSharedType kIsShared,
72           base::NullBehavior Behavior = base::NullBehavior::kRequireNotNull>
73 class V8_NODISCARD ParkedSharedMutexGuardIf final {
74  public:
ParkedSharedMutexGuardIf(LocalIsolate * local_isolate,base::SharedMutex * mutex,bool enable_mutex)75   ParkedSharedMutexGuardIf(LocalIsolate* local_isolate,
76                            base::SharedMutex* mutex, bool enable_mutex)
77       : ParkedSharedMutexGuardIf(local_isolate->heap(), mutex, enable_mutex) {}
ParkedSharedMutexGuardIf(LocalHeap * local_heap,base::SharedMutex * mutex,bool enable_mutex)78   ParkedSharedMutexGuardIf(LocalHeap* local_heap, base::SharedMutex* mutex,
79                            bool enable_mutex) {
80     DCHECK(AllowGarbageCollection::IsAllowed());
81     DCHECK_IMPLIES(Behavior == base::NullBehavior::kRequireNotNull,
82                    mutex != nullptr);
83     if (!enable_mutex) return;
84     mutex_ = mutex;
85 
86     if (kIsShared) {
87       if (!mutex_->TryLockShared()) {
88         ParkedScope scope(local_heap);
89         mutex_->LockShared();
90       }
91     } else {
92       if (!mutex_->TryLockExclusive()) {
93         ParkedScope scope(local_heap);
94         mutex_->LockExclusive();
95       }
96     }
97   }
98   ParkedSharedMutexGuardIf(const ParkedSharedMutexGuardIf&) = delete;
99   ParkedSharedMutexGuardIf& operator=(const ParkedSharedMutexGuardIf&) = delete;
100 
~ParkedSharedMutexGuardIf()101   ~ParkedSharedMutexGuardIf() {
102     if (!mutex_) return;
103 
104     if (kIsShared) {
105       mutex_->UnlockShared();
106     } else {
107       mutex_->UnlockExclusive();
108     }
109   }
110 
111  private:
112   base::SharedMutex* mutex_ = nullptr;
113 };
114 
115 }  // namespace internal
116 }  // namespace v8
117 
118 #endif  // V8_HEAP_PARKED_SCOPE_H_
119