1 /** 2 * Copyright (c) 2021-2022 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 #ifndef PANDA_RUNTIME_MONITOR_POOL_H_ 16 #define PANDA_RUNTIME_MONITOR_POOL_H_ 17 18 #include "libpandabase/os/mutex.h" 19 #include "runtime/include/mem/panda_containers.h" 20 #include "runtime/include/object_header.h" 21 #include "runtime/mark_word.h" 22 #include "runtime/mem/heap_manager.h" 23 #include "runtime/mem/internal_allocator.h" 24 #include "runtime/monitor.h" 25 26 namespace panda { 27 28 class MonitorPool { 29 public: 30 // Likely, we do not need to copy monitor pool 31 NO_COPY_SEMANTIC(MonitorPool); 32 NO_MOVE_SEMANTIC(MonitorPool); 33 34 static constexpr Monitor::MonitorId MAX_MONITOR_ID = MarkWord::MONITOR_POINTER_MAX_COUNT; 35 36 template <class Callback> EnumerateMonitors(const Callback & cb)37 void EnumerateMonitors(const Callback &cb) 38 { 39 os::memory::LockHolder lock(pool_lock_); 40 for (auto &iter : monitors_) { 41 if (!cb(iter.second)) { 42 break; 43 } 44 } 45 } 46 47 template <class Callback> DeflateMonitorsWithCallBack(const Callback & cb)48 void DeflateMonitorsWithCallBack(const Callback &cb) 49 { 50 os::memory::LockHolder lock(pool_lock_); 51 for (auto monitor_iter = monitors_.begin(); monitor_iter != monitors_.end();) { 52 auto monitor = monitor_iter->second; 53 if (cb(monitor) && monitor->DeflateInternal()) { 54 monitor_iter = monitors_.erase(monitor_iter); 55 allocator_->Delete(monitor); 56 } else { 57 monitor_iter++; 58 } 59 } 60 } 61 MonitorPool(mem::InternalAllocatorPtr allocator)62 explicit MonitorPool(mem::InternalAllocatorPtr allocator) : monitors_(allocator->Adapter()) 63 { 64 last_id_ = 0; 65 allocator_ = allocator; 66 } 67 ~MonitorPool()68 ~MonitorPool() 69 { 70 #if defined(PANDA_TSAN_ON) 71 // There is a potential false data race between destroying monitors and daemon threads which are got stuck in a 72 // deadlock. The race is reported for accesses in Mutex::Lock() before going to endless sleep on futex call in 73 // a deadlock. In this case the data race is reported with the main thread, which destroys the mutex. 74 if (os::memory::Mutex::DoNotCheckOnDeadlock()) { 75 TSAN_ANNOTATE_IGNORE_WRITES_BEGIN(); 76 } 77 #endif 78 for (auto &iter : monitors_) { 79 if (iter.second != nullptr) { 80 allocator_->Delete(iter.second); 81 } 82 } 83 #if defined(PANDA_TSAN_ON) 84 if (os::memory::Mutex::DoNotCheckOnDeadlock()) { 85 TSAN_ANNOTATE_IGNORE_WRITES_END(); 86 } 87 #endif 88 } 89 90 Monitor *CreateMonitor(ObjectHeader *obj); 91 92 Monitor *LookupMonitor(Monitor::MonitorId id); 93 94 void FreeMonitor(Monitor::MonitorId id); 95 96 void DeflateMonitors(); 97 98 void ReleaseMonitors(MTManagedThread *thread); 99 100 PandaSet<Monitor::MonitorId> GetEnteredMonitorsIds(MTManagedThread *thread); 101 102 private: 103 mem::InternalAllocatorPtr allocator_; 104 // Lock for private data protection. 105 os::memory::Mutex pool_lock_; 106 107 Monitor::MonitorId last_id_ GUARDED_BY(pool_lock_); 108 PandaUnorderedMap<Monitor::MonitorId, Monitor *> monitors_ GUARDED_BY(pool_lock_); 109 }; 110 111 } // namespace panda 112 113 #endif // PANDA_RUNTIME_MONITOR_POOL_H_ 114