/* * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef COMMON_COMPONENTS_HEAP_COLLECTOR_FINALIZER_PROCESSOR_H #define COMMON_COMPONENTS_HEAP_COLLECTOR_FINALIZER_PROCESSOR_H #include #include #include #include #include "common_components/common/page_allocator.h" #include "common_components/common/type_def.h" #include "common_components/heap/collector/collector.h" #include "common_components/log/log.h" namespace common { template using ManagedList = std::list>; class FinalizerProcessor { public: FinalizerProcessor(); ~FinalizerProcessor() = default; // mainly for resurrection. uint32_t VisitFinalizers(const RootVisitor& visitor) { uint32_t count = 0; std::lock_guard l(listLock_); for (BaseObject*& obj : finalizers_) { visitor(reinterpret_cast(obj)); ++count; } return count; } // for : *finalizers* are not proper gc roots. void VisitGCRoots(const RootVisitor& visitor) { std::lock_guard l(listLock_); for (BaseObject*& obj : finalizables_) { visitor(reinterpret_cast(obj)); } for (BaseObject*& obj : workingFinalizables_) { visitor(reinterpret_cast(obj)); } } // mainly for fixing old pointers void VisitRawPointers(const RootVisitor& visitor) { std::lock_guard l(listLock_); for (BaseObject*& obj : finalizables_) { visitor(reinterpret_cast(obj)); } for (BaseObject*& obj : workingFinalizables_) { visitor(reinterpret_cast(obj)); } for (BaseObject*& obj : finalizers_) { visitor(reinterpret_cast(obj)); } } // notify for finalizer processing loop, invoked after GC void Notify(); // wait started flag set, call after create finalizerProcessor thread void WaitStarted(); void Start(); void Stop(); void Run(); void Init(); void Fini(); void WaitStop(); void EnqueueFinalizables(const std::function& finalizable, uint32_t countLimit = UINT_MAX); void RegisterFinalizer(BaseObject* obj); bool IsRunning() const { return running_; } uint32_t GetTid() const { return tid_; } Mutator* GetMutator() const { return fpMutator_; } void NotifyToReclaimGarbage() { shouldReclaimHeapGarbage_.store(true); } void NotifyToFeedAllocBuffers() { shouldFeedHungryBuffers_.store(true, std::memory_order_release); Notify(); } private: void NotifyStarted(); void Wait(uint32_t timeoutMilliSeconds); void ProcessFinalizables(); void ProcessFinalizableList(); void ReclaimHeapGarbage(); void FeedHungryBuffers(); std::mutex wakeLock_; std::condition_variable wakeCondition_; // notify finalizer processing continue std::mutex startedLock_; std::condition_variable startedCondition_; // notify finalizerProcessor thread is started volatile bool started_; volatile bool running_; // Initially false and set true after finalizerProcessor thread start, set false when stop uint32_t iterationWaitTime_; // finalization std::mutex listLock_; // lock for finalizers & finalizables & workingFinalizables ManagedList finalizers_; // created finalizer record, accessed by mutator & GC // a dead finalizer is moved into finalizable by GC, then run finalize method by FP thread ManagedList finalizables_; ManagedList workingFinalizables_; // FP working list, swap from finalizables std::atomic hasFinalizableJob_; std::atomic shouldReclaimHeapGarbage_; std::atomic shouldFeedHungryBuffers_; #if defined(GCINFO_DEBUG) && GCINFO_DEBUG // stats void LogAfterProcess(); #endif uint64_t timeProcessorBegin_; uint64_t timeProcessUsed_; uint64_t timeCurrentProcessBegin_; uint32_t tid_ = 0; pthread_t threadHandle_ = 0; // thread handle to thread Mutator* fpMutator_ = nullptr; }; } // namespace common #endif // COMMON_COMPONENTS_HEAP_COLLECTOR_FINALIZER_PROCESSOR_H