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