1ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers/* 2ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers * Copyright (C) 2014 The Android Open Source Project 3ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers * 4ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers * Licensed under the Apache License, Version 2.0 (the "License"); 5ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers * you may not use this file except in compliance with the License. 6ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers * You may obtain a copy of the License at 7ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers * 8ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers * http://www.apache.org/licenses/LICENSE-2.0 9ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers * 10ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers * Unless required by applicable law or agreed to in writing, software 11ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers * distributed under the License is distributed on an "AS IS" BASIS, 12ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers * See the License for the specific language governing permissions and 14ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers * limitations under the License. 15ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers */ 16ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 17ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#ifndef ART_RUNTIME_MONITOR_POOL_H_ 18ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#define ART_RUNTIME_MONITOR_POOL_H_ 19ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 20b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers#include "monitor.h" 21b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers 22bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier#include "base/allocator.h" 2344d6ff197b340b5ac2a4094db148b39c366317ddIan Rogers#ifdef __LP64__ 2444d6ff197b340b5ac2a4094db148b39c366317ddIan Rogers#include <stdint.h> 2574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe#include "atomic.h" 2644d6ff197b340b5ac2a4094db148b39c366317ddIan Rogers#include "runtime.h" 2774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe#else 2874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe#include "base/stl_util.h" // STLDeleteElements 2944d6ff197b340b5ac2a4094db148b39c366317ddIan Rogers#endif 30ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 31ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogersnamespace art { 32ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 33ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers// Abstraction to keep monitors small enough to fit in a lock word (32bits). On 32bit systems the 34ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers// monitor id loses the alignment bits of the Monitor*. 35ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogersclass MonitorPool { 36ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers public: 37ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers static MonitorPool* Create() { 38ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#ifndef __LP64__ 39ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers return nullptr; 40ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#else 41ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers return new MonitorPool(); 42ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#endif 43ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers } 44ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 4574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe static Monitor* CreateMonitor(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code) 4674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 4774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe#ifndef __LP64__ 48e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi Monitor* mon = new Monitor(self, owner, obj, hash_code); 49e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi DCHECK_ALIGNED(mon, LockWord::kMonitorIdAlignment); 50e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi return mon; 5174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe#else 5274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe return GetMonitorPool()->CreateMonitorInPool(self, owner, obj, hash_code); 5374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe#endif 5474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } 5574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 5674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe static void ReleaseMonitor(Thread* self, Monitor* monitor) { 5774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe#ifndef __LP64__ 586a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNUSED(self); 5974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe delete monitor; 6074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe#else 6174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe GetMonitorPool()->ReleaseMonitorToPool(self, monitor); 6274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe#endif 6374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } 6474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 65bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier static void ReleaseMonitors(Thread* self, MonitorList::Monitors* monitors) { 6674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe#ifndef __LP64__ 676a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNUSED(self); 6874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe STLDeleteElements(monitors); 6974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe#else 7074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe GetMonitorPool()->ReleaseMonitorsToPool(self, monitors); 7174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe#endif 7274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } 7374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 74ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers static Monitor* MonitorFromMonitorId(MonitorId mon_id) { 75ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#ifndef __LP64__ 76e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi return reinterpret_cast<Monitor*>(mon_id << LockWord::kMonitorIdAlignmentShift); 77ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#else 7874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe return GetMonitorPool()->LookupMonitor(mon_id); 79ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#endif 80ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers } 81ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 82ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers static MonitorId MonitorIdFromMonitor(Monitor* mon) { 83ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#ifndef __LP64__ 84e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi return reinterpret_cast<MonitorId>(mon) >> LockWord::kMonitorIdAlignmentShift; 85ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#else 86ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers return mon->GetMonitorId(); 87ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#endif 88ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers } 89ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 9074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe static MonitorId ComputeMonitorId(Monitor* mon, Thread* self) { 91ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#ifndef __LP64__ 926a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNUSED(self); 93ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers return MonitorIdFromMonitor(mon); 94ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#else 9574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe return GetMonitorPool()->ComputeMonitorIdInPool(mon, self); 96ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#endif 97ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers } 98ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 9974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe static MonitorPool* GetMonitorPool() { 100ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#ifndef __LP64__ 10174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe return nullptr; 102ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#else 10374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe return Runtime::Current()->GetMonitorPool(); 104ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#endif 105ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers } 106ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 107ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers private: 108ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#ifdef __LP64__ 10974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // When we create a monitor pool, threads have not been initialized, yet, so ignore thread-safety 11074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // analysis. 11174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe MonitorPool() NO_THREAD_SAFETY_ANALYSIS; 112ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 11374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe void AllocateChunk() EXCLUSIVE_LOCKS_REQUIRED(Locks::allocated_monitor_ids_lock_); 114ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 11574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe Monitor* CreateMonitorInPool(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code) 11674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 117ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 11874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe void ReleaseMonitorToPool(Thread* self, Monitor* monitor); 119bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier void ReleaseMonitorsToPool(Thread* self, MonitorList::Monitors* monitors); 120ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 12174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Note: This is safe as we do not ever move chunks. 12274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe Monitor* LookupMonitor(MonitorId mon_id) { 12374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe size_t offset = MonitorIdToOffset(mon_id); 12474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe size_t index = offset / kChunkSize; 12574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe size_t offset_in_chunk = offset % kChunkSize; 12674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe uintptr_t base = *(monitor_chunks_.LoadRelaxed()+index); 12774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe return reinterpret_cast<Monitor*>(base + offset_in_chunk); 12874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } 12974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 13074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe static bool IsInChunk(uintptr_t base_addr, Monitor* mon) { 13174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe uintptr_t mon_ptr = reinterpret_cast<uintptr_t>(mon); 13274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe return base_addr <= mon_ptr && (mon_ptr - base_addr < kChunkSize); 13374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } 13474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 13574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Note: This is safe as we do not ever move chunks. 13674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe MonitorId ComputeMonitorIdInPool(Monitor* mon, Thread* self) { 13774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe MutexLock mu(self, *Locks::allocated_monitor_ids_lock_); 13874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe for (size_t index = 0; index < num_chunks_; ++index) { 13974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe uintptr_t chunk_addr = *(monitor_chunks_.LoadRelaxed() + index); 14074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe if (IsInChunk(chunk_addr, mon)) { 1412cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier return OffsetToMonitorId( 1422cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier reinterpret_cast<uintptr_t>(mon) - chunk_addr + index * kChunkSize); 14374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } 14474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } 14574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe LOG(FATAL) << "Did not find chunk that contains monitor."; 14674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe return 0; 14774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } 14874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 14974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe static size_t MonitorIdToOffset(MonitorId id) { 15074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe return id << 3; 15174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } 15274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 15374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe static MonitorId OffsetToMonitorId(size_t offset) { 15474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe return static_cast<MonitorId>(offset >> 3); 15574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } 156ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 15774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // TODO: There are assumptions in the code that monitor addresses are 8B aligned (>>3). 15874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe static constexpr size_t kMonitorAlignment = 8; 15974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Size of a monitor, rounded up to a multiple of alignment. 16074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe static constexpr size_t kAlignedMonitorSize = (sizeof(Monitor) + kMonitorAlignment - 1) & 16174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe -kMonitorAlignment; 16274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // As close to a page as we can get seems a good start. 16374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe static constexpr size_t kChunkCapacity = kPageSize / kAlignedMonitorSize; 16474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Chunk size that is referenced in the id. We can collapse this to the actually used storage 16574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // in a chunk, i.e., kChunkCapacity * kAlignedMonitorSize, but this will mean proper divisions. 16674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe static constexpr size_t kChunkSize = kPageSize; 16774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // The number of initial chunks storable in monitor_chunks_. The number is large enough to make 16874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // resizing unlikely, but small enough to not waste too much memory. 16974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe static constexpr size_t kInitialChunkStorage = 8U; 17074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 17174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // List of memory chunks. Each chunk is kChunkSize. 17274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe Atomic<uintptr_t*> monitor_chunks_; 17374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Number of chunks stored. 17474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe size_t num_chunks_ GUARDED_BY(Locks::allocated_monitor_ids_lock_); 17574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Number of chunks storable. 17674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe size_t capacity_ GUARDED_BY(Locks::allocated_monitor_ids_lock_); 17774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 17874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // To avoid race issues when resizing, we keep all the previous arrays. 17974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe std::vector<uintptr_t*> old_chunk_arrays_ GUARDED_BY(Locks::allocated_monitor_ids_lock_); 18074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 18113735955f39b3b304c37d2b2840663c131262c18Ian Rogers typedef TrackingAllocator<uint8_t, kAllocatorTagMonitorPool> Allocator; 182bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier Allocator allocator_; 183bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier 18474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Start of free list of monitors. 18574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Note: these point to the right memory regions, but do *not* denote initialized objects. 18674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe Monitor* first_free_ GUARDED_BY(Locks::allocated_monitor_ids_lock_); 187ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#endif 188ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers}; 189ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 190ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers} // namespace art 191ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 192ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#endif // ART_RUNTIME_MONITOR_POOL_H_ 193