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