1 /* 2 * Copyright (c) 2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef COMMON_COMPONENTS_HEAP_COLLECTOR_FINALIZER_PROCESSOR_H 17 #define COMMON_COMPONENTS_HEAP_COLLECTOR_FINALIZER_PROCESSOR_H 18 19 #include <climits> 20 #include <condition_variable> 21 #include <list> 22 #include <mutex> 23 24 #include "common_components/common/page_allocator.h" 25 #include "common_components/common/type_def.h" 26 #include "common_components/heap/collector/collector.h" 27 #include "common_components/log/log.h" 28 29 namespace common { 30 template<typename T> 31 using ManagedList = std::list<T, StdContainerAllocator<T, FINALIZER_PROCESSOR>>; 32 33 class FinalizerProcessor { 34 public: 35 FinalizerProcessor(); 36 ~FinalizerProcessor() = default; 37 38 // mainly for resurrection. VisitFinalizers(const RootVisitor & visitor)39 uint32_t VisitFinalizers(const RootVisitor& visitor) 40 { 41 uint32_t count = 0; 42 std::lock_guard<std::mutex> l(listLock_); 43 for (BaseObject*& obj : finalizers_) { 44 visitor(reinterpret_cast<ObjectRef&>(obj)); 45 ++count; 46 } 47 return count; 48 } 49 50 // for : *finalizers* are not proper gc roots. VisitGCRoots(const RootVisitor & visitor)51 void VisitGCRoots(const RootVisitor& visitor) 52 { 53 std::lock_guard<std::mutex> l(listLock_); 54 for (BaseObject*& obj : finalizables_) { 55 visitor(reinterpret_cast<ObjectRef&>(obj)); 56 } 57 for (BaseObject*& obj : workingFinalizables_) { 58 visitor(reinterpret_cast<ObjectRef&>(obj)); 59 } 60 } 61 62 // mainly for fixing old pointers VisitRawPointers(const RootVisitor & visitor)63 void VisitRawPointers(const RootVisitor& visitor) 64 { 65 std::lock_guard<std::mutex> l(listLock_); 66 for (BaseObject*& obj : finalizables_) { 67 visitor(reinterpret_cast<ObjectRef&>(obj)); 68 } 69 for (BaseObject*& obj : workingFinalizables_) { 70 visitor(reinterpret_cast<ObjectRef&>(obj)); 71 } 72 for (BaseObject*& obj : finalizers_) { 73 visitor(reinterpret_cast<ObjectRef&>(obj)); 74 } 75 } 76 77 // notify for finalizer processing loop, invoked after GC 78 void Notify(); 79 // wait started flag set, call after create finalizerProcessor thread 80 void WaitStarted(); 81 82 void Start(); 83 void Stop(); 84 void Run(); 85 void Init(); 86 void Fini(); 87 void WaitStop(); 88 89 void EnqueueFinalizables(const std::function<bool(BaseObject*)>& finalizable, uint32_t countLimit = UINT_MAX); 90 void RegisterFinalizer(BaseObject* obj); IsRunning()91 bool IsRunning() const { return running_; } GetTid()92 uint32_t GetTid() const { return tid_; } 93 GetMutator()94 Mutator* GetMutator() const { return fpMutator_; } 95 NotifyToReclaimGarbage()96 void NotifyToReclaimGarbage() { shouldReclaimHeapGarbage_.store(true); } NotifyToFeedAllocBuffers()97 void NotifyToFeedAllocBuffers() 98 { 99 shouldFeedHungryBuffers_.store(true, std::memory_order_release); 100 Notify(); 101 } 102 103 private: 104 void NotifyStarted(); 105 void Wait(uint32_t timeoutMilliSeconds); 106 void ProcessFinalizables(); 107 void ProcessFinalizableList(); 108 void ReclaimHeapGarbage(); 109 void FeedHungryBuffers(); 110 111 std::mutex wakeLock_; 112 std::condition_variable wakeCondition_; // notify finalizer processing continue 113 114 std::mutex startedLock_; 115 std::condition_variable startedCondition_; // notify finalizerProcessor thread is started 116 volatile bool started_; 117 118 volatile bool running_; // Initially false and set true after finalizerProcessor thread start, set false when stop 119 120 uint32_t iterationWaitTime_; 121 122 // finalization 123 std::mutex listLock_; // lock for finalizers & finalizables & workingFinalizables 124 ManagedList<BaseObject*> finalizers_; // created finalizer record, accessed by mutator & GC 125 126 // a dead finalizer is moved into finalizable by GC, then run finalize method by FP thread 127 ManagedList<BaseObject*> finalizables_; 128 129 ManagedList<BaseObject*> workingFinalizables_; // FP working list, swap from finalizables 130 131 std::atomic<bool> hasFinalizableJob_; 132 std::atomic<bool> shouldReclaimHeapGarbage_; 133 std::atomic<bool> shouldFeedHungryBuffers_; 134 #if defined(GCINFO_DEBUG) && GCINFO_DEBUG 135 // stats 136 void LogAfterProcess(); 137 #endif 138 uint64_t timeProcessorBegin_; 139 uint64_t timeProcessUsed_; 140 uint64_t timeCurrentProcessBegin_; 141 uint32_t tid_ = 0; 142 pthread_t threadHandle_ = 0; // thread handle to thread 143 Mutator* fpMutator_ = nullptr; 144 }; 145 } // namespace common 146 147 #endif // COMMON_COMPONENTS_HEAP_COLLECTOR_FINALIZER_PROCESSOR_H 148