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> 258f4b056427a9d2321e3aa4f21ca8ffb18b3e5ae6David Sehr#include "base/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) 46bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(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 107057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe ~MonitorPool() { 108057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe#ifdef __LP64__ 109057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe FreeInternal(); 110057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe#endif 111057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe } 112057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe 113ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers private: 114ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#ifdef __LP64__ 11574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // When we create a monitor pool, threads have not been initialized, yet, so ignore thread-safety 11674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // analysis. 11774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe MonitorPool() NO_THREAD_SAFETY_ANALYSIS; 118ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 11990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier void AllocateChunk() REQUIRES(Locks::allocated_monitor_ids_lock_); 120ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 121057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe // Release all chunks and metadata. This is done on shutdown, where threads have been destroyed, 122057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe // so ignore thead-safety analysis. 123057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe void FreeInternal() NO_THREAD_SAFETY_ANALYSIS; 124057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe 12574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe Monitor* CreateMonitorInPool(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code) 126bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_); 127ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 12874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe void ReleaseMonitorToPool(Thread* self, Monitor* monitor); 129bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier void ReleaseMonitorsToPool(Thread* self, MonitorList::Monitors* monitors); 130ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 131a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // Note: This is safe as we do not ever move chunks. All needed entries in the monitor_chunks_ 132a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // data structure are read-only once we get here. Updates happen-before this call because 133a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // the lock word was stored with release semantics and we read it with acquire semantics to 134a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // retrieve the id. 13574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe Monitor* LookupMonitor(MonitorId mon_id) { 13674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe size_t offset = MonitorIdToOffset(mon_id); 13774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe size_t index = offset / kChunkSize; 138a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm size_t top_index = index / kMaxListSize; 139a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm size_t list_index = index % kMaxListSize; 14074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe size_t offset_in_chunk = offset % kChunkSize; 141a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm uintptr_t base = monitor_chunks_[top_index][list_index]; 14274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe return reinterpret_cast<Monitor*>(base + offset_in_chunk); 14374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } 14474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 14574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe static bool IsInChunk(uintptr_t base_addr, Monitor* mon) { 14674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe uintptr_t mon_ptr = reinterpret_cast<uintptr_t>(mon); 14774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe return base_addr <= mon_ptr && (mon_ptr - base_addr < kChunkSize); 14874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } 14974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 15074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe MonitorId ComputeMonitorIdInPool(Monitor* mon, Thread* self) { 15174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe MutexLock mu(self, *Locks::allocated_monitor_ids_lock_); 152a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm for (size_t i = 0; i <= current_chunk_list_index_; ++i) { 153a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm for (size_t j = 0; j < ChunkListCapacity(i); ++j) { 154a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm if (j >= num_chunks_ && i == current_chunk_list_index_) { 155a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm break; 156a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm } 157a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm uintptr_t chunk_addr = monitor_chunks_[i][j]; 158a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm if (IsInChunk(chunk_addr, mon)) { 159a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm return OffsetToMonitorId( 160a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm reinterpret_cast<uintptr_t>(mon) - chunk_addr 161a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm + i * (kMaxListSize * kChunkSize) + j * kChunkSize); 162a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm } 16374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } 16474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } 16574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe LOG(FATAL) << "Did not find chunk that contains monitor."; 16674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe return 0; 16774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } 16874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 169a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm static constexpr size_t MonitorIdToOffset(MonitorId id) { 17074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe return id << 3; 17174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } 17274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 173a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm static constexpr MonitorId OffsetToMonitorId(size_t offset) { 17474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe return static_cast<MonitorId>(offset >> 3); 17574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } 176ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 177a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm static constexpr size_t ChunkListCapacity(size_t index) { 178a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm return kInitialChunkStorage << index; 179a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm } 180a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm 18174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // TODO: There are assumptions in the code that monitor addresses are 8B aligned (>>3). 18274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe static constexpr size_t kMonitorAlignment = 8; 18374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Size of a monitor, rounded up to a multiple of alignment. 18474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe static constexpr size_t kAlignedMonitorSize = (sizeof(Monitor) + kMonitorAlignment - 1) & 18574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe -kMonitorAlignment; 18674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // As close to a page as we can get seems a good start. 18774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe static constexpr size_t kChunkCapacity = kPageSize / kAlignedMonitorSize; 18874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Chunk size that is referenced in the id. We can collapse this to the actually used storage 18974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // in a chunk, i.e., kChunkCapacity * kAlignedMonitorSize, but this will mean proper divisions. 19074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe static constexpr size_t kChunkSize = kPageSize; 191a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm static_assert(IsPowerOfTwo(kChunkSize), "kChunkSize must be power of 2"); 192a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // The number of chunks of storage that can be referenced by the initial chunk list. 193a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // The total number of usable monitor chunks is typically 255 times this number, so it 194a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // should be large enough that we don't run out. We run out of address bits if it's > 512. 195a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // Currently we set it a bit smaller, to save half a page per process. We make it tiny in 196a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // debug builds to catch growth errors. The only value we really expect to tune. 197a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm static constexpr size_t kInitialChunkStorage = kIsDebugBuild ? 1U : 256U; 198a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm static_assert(IsPowerOfTwo(kInitialChunkStorage), "kInitialChunkStorage must be power of 2"); 199a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // The number of lists, each containing pointers to storage chunks. 200a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm static constexpr size_t kMaxChunkLists = 8; // Dictated by 3 bit index. Don't increase above 8. 201a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm static_assert(IsPowerOfTwo(kMaxChunkLists), "kMaxChunkLists must be power of 2"); 202a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm static constexpr size_t kMaxListSize = kInitialChunkStorage << (kMaxChunkLists - 1); 203a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // We lose 3 bits in monitor id due to 3 bit monitor_chunks_ index, and gain it back from 204a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // the 3 bit alignment constraint on monitors: 205a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm static_assert(kMaxListSize * kChunkSize < (1 << LockWord::kMonitorIdSize), 206a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm "Monitor id bits don't fit"); 207a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm static_assert(IsPowerOfTwo(kMaxListSize), "kMaxListSize must be power of 2"); 208a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm 209a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // Array of pointers to lists (again arrays) of pointers to chunks containing monitors. 210a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // Zeroth entry points to a list (array) of kInitialChunkStorage pointers to chunks. 211a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // Each subsequent list as twice as large as the preceding one. 212a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // Monitor Ids are interpreted as follows: 213a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // Top 3 bits (of 28): index into monitor_chunks_. 214a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // Next 16 bits: index into the chunk list, i.e. monitor_chunks_[i]. 215a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // Last 9 bits: offset within chunk, expressed as multiple of kMonitorAlignment. 216a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // If we set kInitialChunkStorage to 512, this would allow us to use roughly 128K chunks of 217a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // monitors, which is 0.5GB of monitors. With this maximum setting, the largest chunk list 218a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // contains 64K entries, and we make full use of the available index space. With a 219a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // kInitialChunkStorage value of 256, this is proportionately reduced to 0.25GB of monitors. 220a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // Updates to monitor_chunks_ are guarded by allocated_monitor_ids_lock_ . 221a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // No field in this entire data structure is ever updated once a monitor id whose lookup 222a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // requires it has been made visible to another thread. Thus readers never race with 223a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // updates, in spite of the fact that they acquire no locks. 224a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm uintptr_t* monitor_chunks_[kMaxChunkLists]; // uintptr_t is really a Monitor* . 225a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // Highest currently used index in monitor_chunks_ . Used for newly allocated chunks. 226a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm size_t current_chunk_list_index_ GUARDED_BY(Locks::allocated_monitor_ids_lock_); 227a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // Number of chunk pointers stored in monitor_chunks_[current_chunk_list_index_] so far. 22874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe size_t num_chunks_ GUARDED_BY(Locks::allocated_monitor_ids_lock_); 229a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // After the initial allocation, this is always equal to 230a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // ChunkListCapacity(current_chunk_list_index_). 231a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm size_t current_chunk_list_capacity_ GUARDED_BY(Locks::allocated_monitor_ids_lock_); 23274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 23313735955f39b3b304c37d2b2840663c131262c18Ian Rogers typedef TrackingAllocator<uint8_t, kAllocatorTagMonitorPool> Allocator; 234bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier Allocator allocator_; 235bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier 23674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Start of free list of monitors. 23774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Note: these point to the right memory regions, but do *not* denote initialized objects. 23874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe Monitor* first_free_ GUARDED_BY(Locks::allocated_monitor_ids_lock_); 239ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#endif 240ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers}; 241ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 242ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers} // namespace art 243ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 244ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#endif // ART_RUNTIME_MONITOR_POOL_H_ 245