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