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/mutex.h"
21 #include "object_callbacks.h"
22 #include "thread-inl.h"
23 
24 namespace art {
25 namespace gc {
26 
27 class AbstractSystemWeakHolder {
28  public:
~AbstractSystemWeakHolder()29   virtual ~AbstractSystemWeakHolder() {}
30 
31   virtual void Allow() REQUIRES_SHARED(Locks::mutator_lock_) = 0;
32   virtual void Disallow() REQUIRES_SHARED(Locks::mutator_lock_) = 0;
33   // See Runtime::BroadcastForNewSystemWeaks for the broadcast_for_checkpoint definition.
34   virtual void Broadcast(bool broadcast_for_checkpoint) = 0;
35 
36   virtual void Sweep(IsMarkedVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_) = 0;
37 };
38 
39 class SystemWeakHolder : public AbstractSystemWeakHolder {
40  public:
SystemWeakHolder(LockLevel level)41   explicit SystemWeakHolder(LockLevel level)
42       : allow_disallow_lock_("SystemWeakHolder", level),
43         new_weak_condition_("SystemWeakHolder new condition", allow_disallow_lock_),
44         allow_new_system_weak_(true) {
45   }
~SystemWeakHolder()46   virtual ~SystemWeakHolder() {}
47 
Allow()48   void Allow() OVERRIDE
49       REQUIRES_SHARED(Locks::mutator_lock_)
50       REQUIRES(!allow_disallow_lock_) {
51     CHECK(!kUseReadBarrier);
52     MutexLock mu(Thread::Current(), allow_disallow_lock_);
53     allow_new_system_weak_ = true;
54     new_weak_condition_.Broadcast(Thread::Current());
55   }
56 
Disallow()57   void Disallow() OVERRIDE
58       REQUIRES_SHARED(Locks::mutator_lock_)
59       REQUIRES(!allow_disallow_lock_) {
60     CHECK(!kUseReadBarrier);
61     MutexLock mu(Thread::Current(), allow_disallow_lock_);
62     allow_new_system_weak_ = false;
63   }
64 
Broadcast(bool broadcast_for_checkpoint ATTRIBUTE_UNUSED)65   void Broadcast(bool broadcast_for_checkpoint ATTRIBUTE_UNUSED) OVERRIDE
66       REQUIRES(!allow_disallow_lock_) {
67     MutexLock mu(Thread::Current(), allow_disallow_lock_);
68     new_weak_condition_.Broadcast(Thread::Current());
69   }
70 
71   // WARNING: For lock annotations only.
GetAllowDisallowLock()72   Mutex* GetAllowDisallowLock() const RETURN_CAPABILITY(allow_disallow_lock_) {
73     return nullptr;
74   }
75 
76  protected:
Wait(Thread * self)77   void Wait(Thread* self)
78       REQUIRES_SHARED(Locks::mutator_lock_)
79       REQUIRES(allow_disallow_lock_) {
80     // Wait for GC's sweeping to complete and allow new records
81     while (UNLIKELY((!kUseReadBarrier && !allow_new_system_weak_) ||
82                     (kUseReadBarrier && !self->GetWeakRefAccessEnabled()))) {
83       // Check and run the empty checkpoint before blocking so the empty checkpoint will work in the
84       // presence of threads blocking for weak ref access.
85       self->CheckEmptyCheckpointFromWeakRefAccess(&allow_disallow_lock_);
86       new_weak_condition_.WaitHoldingLocks(self);
87     }
88   }
89 
90   Mutex allow_disallow_lock_;
91   ConditionVariable new_weak_condition_ GUARDED_BY(allow_disallow_lock_);
92   bool allow_new_system_weak_ GUARDED_BY(allow_disallow_lock_);
93 };
94 
95 }  // namespace gc
96 }  // namespace art
97 
98 #endif  // ART_RUNTIME_GC_SYSTEM_WEAK_H_
99