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#include "monitor_pool.h" 18ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 1957943810cfc789da890d73621741729da5feaaf8Andreas Gampe#include "base/logging.h" // For VLOG. 20ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#include "base/mutex-inl.h" 21ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#include "monitor.h" 228cf9cb386cd9286d67e879f1ee501ec00d72a4e1Andreas Gampe#include "thread-current-inl.h" 23ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 24ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogersnamespace art { 25ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 2674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampenamespace mirror { 272ffb703bf431d74326c88266b4ddaf225eb3c6adIgor Murashkinclass Object; 2874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe} // namespace mirror 29ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 3074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas GampeMonitorPool::MonitorPool() 31a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm : current_chunk_list_index_(0), num_chunks_(0), current_chunk_list_capacity_(0), 32a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm first_free_(nullptr) { 33a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm for (size_t i = 0; i < kMaxChunkLists; ++i) { 34a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm monitor_chunks_[i] = nullptr; // Not absolutely required, but ... 35a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm } 3674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe AllocateChunk(); // Get our first chunk. 37ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers} 38ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 3974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe// Assumes locks are held appropriately when necessary. 4074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe// We do not need a lock in the constructor, but we need one when in CreateMonitorInPool. 4174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampevoid MonitorPool::AllocateChunk() { 4274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe DCHECK(first_free_ == nullptr); 4374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 44a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm // Do we need to allocate another chunk list? 45a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm if (num_chunks_ == current_chunk_list_capacity_) { 46a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm if (current_chunk_list_capacity_ != 0U) { 47a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm ++current_chunk_list_index_; 48a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm CHECK_LT(current_chunk_list_index_, kMaxChunkLists) << "Out of space for inflated monitors"; 49a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm VLOG(monitor) << "Expanding to capacity " 50a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm << 2 * ChunkListCapacity(current_chunk_list_index_) - kInitialChunkStorage; 51a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm } // else we're initializing 52a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm current_chunk_list_capacity_ = ChunkListCapacity(current_chunk_list_index_); 53a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm uintptr_t* new_list = new uintptr_t[current_chunk_list_capacity_](); 54a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm DCHECK(monitor_chunks_[current_chunk_list_index_] == nullptr); 55a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm monitor_chunks_[current_chunk_list_index_] = new_list; 56a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm num_chunks_ = 0; 57ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers } 5874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 5974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Allocate the chunk. 60bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier void* chunk = allocator_.allocate(kChunkSize); 6174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Check we allocated memory. 6274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe CHECK_NE(reinterpret_cast<uintptr_t>(nullptr), reinterpret_cast<uintptr_t>(chunk)); 6374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Check it is aligned as we need it. 6474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe CHECK_EQ(0U, reinterpret_cast<uintptr_t>(chunk) % kMonitorAlignment); 6574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 6674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Add the chunk. 67a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm monitor_chunks_[current_chunk_list_index_][num_chunks_] = reinterpret_cast<uintptr_t>(chunk); 6874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe num_chunks_++; 6974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 7074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Set up the free list 7174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe Monitor* last = reinterpret_cast<Monitor*>(reinterpret_cast<uintptr_t>(chunk) + 7274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe (kChunkCapacity - 1) * kAlignedMonitorSize); 7374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe last->next_free_ = nullptr; 7474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Eagerly compute id. 75a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm last->monitor_id_ = OffsetToMonitorId(current_chunk_list_index_* (kMaxListSize * kChunkSize) 76a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm + (num_chunks_ - 1) * kChunkSize + (kChunkCapacity - 1) * kAlignedMonitorSize); 7774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe for (size_t i = 0; i < kChunkCapacity - 1; ++i) { 7874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe Monitor* before = reinterpret_cast<Monitor*>(reinterpret_cast<uintptr_t>(last) - 7974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe kAlignedMonitorSize); 8074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe before->next_free_ = last; 8174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Derive monitor_id from last. 8274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe before->monitor_id_ = OffsetToMonitorId(MonitorIdToOffset(last->monitor_id_) - 8374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe kAlignedMonitorSize); 8474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 8574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe last = before; 8674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } 8774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe DCHECK(last == reinterpret_cast<Monitor*>(chunk)); 8874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe first_free_ = last; 8974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe} 9074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 91057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampevoid MonitorPool::FreeInternal() { 92057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe // This is on shutdown with NO_THREAD_SAFETY_ANALYSIS, can't/don't need to lock. 93a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm DCHECK_NE(current_chunk_list_capacity_, 0UL); 94a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm for (size_t i = 0; i <= current_chunk_list_index_; ++i) { 95a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm DCHECK_NE(monitor_chunks_[i], static_cast<uintptr_t*>(nullptr)); 96a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm for (size_t j = 0; j < ChunkListCapacity(i); ++j) { 97a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm if (i < current_chunk_list_index_ || j < num_chunks_) { 98a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm DCHECK_NE(monitor_chunks_[i][j], 0U); 99a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm allocator_.deallocate(reinterpret_cast<uint8_t*>(monitor_chunks_[i][j]), kChunkSize); 100a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm } else { 101a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm DCHECK_EQ(monitor_chunks_[i][j], 0U); 102a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm } 103057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe } 104a319f4dbeea00701a0d12dc39b7bf0a5323f6b2aHans Boehm delete[] monitor_chunks_[i]; 105057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe } 106057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe} 107057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe 10874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas GampeMonitor* MonitorPool::CreateMonitorInPool(Thread* self, Thread* owner, mirror::Object* obj, 10974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe int32_t hash_code) 110bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 11174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // We are gonna allocate, so acquire the writer lock. 11274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe MutexLock mu(self, *Locks::allocated_monitor_ids_lock_); 11374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 11474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Enough space, or need to resize? 11574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe if (first_free_ == nullptr) { 1162c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier VLOG(monitor) << "Allocating a new chunk."; 11774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe AllocateChunk(); 11874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } 11974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 12074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe Monitor* mon_uninitialized = first_free_; 12174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe first_free_ = first_free_->next_free_; 12274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 12374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Pull out the id which was preinitialized. 12474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe MonitorId id = mon_uninitialized->monitor_id_; 12574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 12674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Initialize it. 12774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe Monitor* monitor = new(mon_uninitialized) Monitor(self, owner, obj, hash_code, id); 12874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 12974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe return monitor; 130ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers} 131ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 13274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampevoid MonitorPool::ReleaseMonitorToPool(Thread* self, Monitor* monitor) { 13374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Might be racy with allocation, so acquire lock. 13474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe MutexLock mu(self, *Locks::allocated_monitor_ids_lock_); 13574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 13674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Keep the monitor id. Don't trust it's not cleared. 13774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe MonitorId id = monitor->monitor_id_; 13874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 13974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Call the destructor. 14074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // TODO: Exception safety? 14174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe monitor->~Monitor(); 14274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 14374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Add to the head of the free list. 14474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe monitor->next_free_ = first_free_; 14574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe first_free_ = monitor; 14674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 14774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Rewrite monitor id. 14874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe monitor->monitor_id_ = id; 14974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe} 15074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 151bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartiervoid MonitorPool::ReleaseMonitorsToPool(Thread* self, MonitorList::Monitors* monitors) { 15274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe for (Monitor* mon : *monitors) { 15374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe ReleaseMonitorToPool(self, mon); 15474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } 155ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers} 156ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 157ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers} // namespace art 158