1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_RUNTIME_GC_SYSTEM_WEAK_H_
18 #define ART_RUNTIME_GC_SYSTEM_WEAK_H_
19 
20 #include "base/macros.h"
21 #include "base/mutex.h"
22 #include "object_callbacks.h"
23 #include "thread-inl.h"
24 
25 namespace art HIDDEN {
26 namespace gc {
27 
28 class AbstractSystemWeakHolder {
29  public:
~AbstractSystemWeakHolder()30   virtual ~AbstractSystemWeakHolder() {}
31 
32   virtual void Allow() REQUIRES_SHARED(Locks::mutator_lock_) = 0;
33   virtual void Disallow() REQUIRES_SHARED(Locks::mutator_lock_) = 0;
34   // See Runtime::BroadcastForNewSystemWeaks for the broadcast_for_checkpoint definition.
35   virtual void Broadcast(bool broadcast_for_checkpoint) = 0;
36 
37   virtual void Sweep(IsMarkedVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_) = 0;
38 };
39 
40 class SystemWeakHolder : public AbstractSystemWeakHolder {
41  public:
SystemWeakHolder(LockLevel level)42   explicit SystemWeakHolder(LockLevel level)
43       : allow_disallow_lock_("SystemWeakHolder", level),
44         new_weak_condition_("SystemWeakHolder new condition", allow_disallow_lock_),
45         allow_new_system_weak_(true) {
46   }
~SystemWeakHolder()47   virtual ~SystemWeakHolder() {}
48 
Allow()49   void Allow() override
50       REQUIRES_SHARED(Locks::mutator_lock_)
51       REQUIRES(!allow_disallow_lock_) {
52     CHECK(!gUseReadBarrier);
53     MutexLock mu(Thread::Current(), allow_disallow_lock_);
54     allow_new_system_weak_ = true;
55     new_weak_condition_.Broadcast(Thread::Current());
56   }
57 
Disallow()58   void Disallow() override
59       REQUIRES_SHARED(Locks::mutator_lock_)
60       REQUIRES(!allow_disallow_lock_) {
61     CHECK(!gUseReadBarrier);
62     MutexLock mu(Thread::Current(), allow_disallow_lock_);
63     allow_new_system_weak_ = false;
64   }
65 
Broadcast(bool broadcast_for_checkpoint)66   void Broadcast([[maybe_unused]] bool broadcast_for_checkpoint) override
67       REQUIRES(!allow_disallow_lock_) {
68     MutexLock mu(Thread::Current(), allow_disallow_lock_);
69     new_weak_condition_.Broadcast(Thread::Current());
70   }
71 
72   // WARNING: For lock annotations only.
GetAllowDisallowLock()73   Mutex* GetAllowDisallowLock() const RETURN_CAPABILITY(allow_disallow_lock_) {
74     return nullptr;
75   }
76 
77  protected:
Wait(Thread * self)78   void Wait(Thread* self)
79       REQUIRES_SHARED(Locks::mutator_lock_)
80       REQUIRES(allow_disallow_lock_) {
81     // Wait for GC's sweeping to complete and allow new records
82     while (UNLIKELY((!gUseReadBarrier && !allow_new_system_weak_) ||
83                     (gUseReadBarrier && !self->GetWeakRefAccessEnabled()))) {
84       // Check and run the empty checkpoint before blocking so the empty checkpoint will work in the
85       // presence of threads blocking for weak ref access.
86       self->CheckEmptyCheckpointFromWeakRefAccess(&allow_disallow_lock_);
87       new_weak_condition_.WaitHoldingLocks(self);
88     }
89   }
90 
91   Mutex allow_disallow_lock_;
92   ConditionVariable new_weak_condition_ GUARDED_BY(allow_disallow_lock_);
93   bool allow_new_system_weak_ GUARDED_BY(allow_disallow_lock_);
94 };
95 
96 }  // namespace gc
97 }  // namespace art
98 
99 #endif  // ART_RUNTIME_GC_SYSTEM_WEAK_H_
100