monitor_pool.cc revision 057134bdf40981555a8bf56ab8d703a503b40f8f
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 19ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#include "base/logging.h" 20ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#include "base/mutex-inl.h" 2144d6ff197b340b5ac2a4094db148b39c366317ddIan Rogers#include "thread-inl.h" 22ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#include "monitor.h" 23ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 24ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogersnamespace art { 25ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 2674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampenamespace mirror { 2774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe class Object; 2874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe} // namespace mirror 29ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 3074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas GampeMonitorPool::MonitorPool() 3174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe : num_chunks_(0), capacity_(0), first_free_(nullptr) { 3274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe AllocateChunk(); // Get our first chunk. 33ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers} 34ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 3574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe// Assumes locks are held appropriately when necessary. 3674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe// We do not need a lock in the constructor, but we need one when in CreateMonitorInPool. 3774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampevoid MonitorPool::AllocateChunk() { 3874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe DCHECK(first_free_ == nullptr); 3974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 4074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Do we need to resize? 4174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe if (num_chunks_ == capacity_) { 4274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe if (capacity_ == 0U) { 4374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Initialization. 4474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe capacity_ = kInitialChunkStorage; 45057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe uintptr_t* new_backing = new uintptr_t[capacity_](); 46057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe DCHECK(monitor_chunks_.LoadRelaxed() == nullptr); 4774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe monitor_chunks_.StoreRelaxed(new_backing); 4874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } else { 4974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe size_t new_capacity = 2 * capacity_; 50057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe uintptr_t* new_backing = new uintptr_t[new_capacity](); 5174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe uintptr_t* old_backing = monitor_chunks_.LoadRelaxed(); 5274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe memcpy(new_backing, old_backing, sizeof(uintptr_t) * capacity_); 5374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe monitor_chunks_.StoreRelaxed(new_backing); 5474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe capacity_ = new_capacity; 554464a3efcf8dcddfb00d7db0c3add9a7acb6642eAndreas Gampe old_chunk_arrays_.push_back(std::unique_ptr<uintptr_t[]>(old_backing)); 562c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier VLOG(monitor) << "Resizing to capacity " << capacity_; 57ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers } 58ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers } 5974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 6074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Allocate the chunk. 61bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier void* chunk = allocator_.allocate(kChunkSize); 6274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Check we allocated memory. 6374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe CHECK_NE(reinterpret_cast<uintptr_t>(nullptr), reinterpret_cast<uintptr_t>(chunk)); 6474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Check it is aligned as we need it. 6574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe CHECK_EQ(0U, reinterpret_cast<uintptr_t>(chunk) % kMonitorAlignment); 6674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 6774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Add the chunk. 682c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier *(monitor_chunks_.LoadRelaxed() + num_chunks_) = reinterpret_cast<uintptr_t>(chunk); 6974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe num_chunks_++; 7074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 7174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Set up the free list 7274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe Monitor* last = reinterpret_cast<Monitor*>(reinterpret_cast<uintptr_t>(chunk) + 7374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe (kChunkCapacity - 1) * kAlignedMonitorSize); 7474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe last->next_free_ = nullptr; 7574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Eagerly compute id. 7674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe last->monitor_id_ = OffsetToMonitorId((num_chunks_ - 1) * kChunkSize + 7774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe (kChunkCapacity - 1) * kAlignedMonitorSize); 7874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe for (size_t i = 0; i < kChunkCapacity - 1; ++i) { 7974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe Monitor* before = reinterpret_cast<Monitor*>(reinterpret_cast<uintptr_t>(last) - 8074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe kAlignedMonitorSize); 8174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe before->next_free_ = last; 8274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Derive monitor_id from last. 8374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe before->monitor_id_ = OffsetToMonitorId(MonitorIdToOffset(last->monitor_id_) - 8474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe kAlignedMonitorSize); 8574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 8674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe last = before; 8774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } 8874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe DCHECK(last == reinterpret_cast<Monitor*>(chunk)); 8974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe first_free_ = last; 9074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe} 9174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 92057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampevoid MonitorPool::FreeInternal() { 93057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe // This is on shutdown with NO_THREAD_SAFETY_ANALYSIS, can't/don't need to lock. 94057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe uintptr_t* backing = monitor_chunks_.LoadRelaxed(); 95057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe DCHECK(backing != nullptr); 96057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe DCHECK_GT(capacity_, 0U); 97057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe DCHECK_GT(num_chunks_, 0U); 98057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe 99057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe for (size_t i = 0; i < capacity_; ++i) { 100057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe if (i < num_chunks_) { 101057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe DCHECK_NE(backing[i], 0U); 102057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe allocator_.deallocate(reinterpret_cast<uint8_t*>(backing[i]), kChunkSize); 103057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe } else { 104057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe DCHECK_EQ(backing[i], 0U); 105057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe } 106057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe } 107057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe 108057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe delete[] backing; 109057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe} 110057134bdf40981555a8bf56ab8d703a503b40f8fAndreas Gampe 11174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas GampeMonitor* MonitorPool::CreateMonitorInPool(Thread* self, Thread* owner, mirror::Object* obj, 11274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe int32_t hash_code) 11390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 11474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // We are gonna allocate, so acquire the writer lock. 11574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe MutexLock mu(self, *Locks::allocated_monitor_ids_lock_); 11674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 11774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Enough space, or need to resize? 11874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe if (first_free_ == nullptr) { 1192c26501d24d929abe096ecce44f91410290b33c0Mathieu Chartier VLOG(monitor) << "Allocating a new chunk."; 12074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe AllocateChunk(); 12174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } 12274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 12374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe Monitor* mon_uninitialized = first_free_; 12474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe first_free_ = first_free_->next_free_; 12574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 12674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Pull out the id which was preinitialized. 12774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe MonitorId id = mon_uninitialized->monitor_id_; 12874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 12974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Initialize it. 13074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe Monitor* monitor = new(mon_uninitialized) Monitor(self, owner, obj, hash_code, id); 13174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 13274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe return monitor; 133ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers} 134ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 13574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampevoid MonitorPool::ReleaseMonitorToPool(Thread* self, Monitor* monitor) { 13674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Might be racy with allocation, so acquire lock. 13774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe MutexLock mu(self, *Locks::allocated_monitor_ids_lock_); 13874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 13974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Keep the monitor id. Don't trust it's not cleared. 14074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe MonitorId id = monitor->monitor_id_; 14174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 14274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Call the destructor. 14374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // TODO: Exception safety? 14474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe monitor->~Monitor(); 14574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 14674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Add to the head of the free list. 14774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe monitor->next_free_ = first_free_; 14874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe first_free_ = monitor; 14974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 15074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe // Rewrite monitor id. 15174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe monitor->monitor_id_ = id; 15274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe} 15374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe 154bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartiervoid MonitorPool::ReleaseMonitorsToPool(Thread* self, MonitorList::Monitors* monitors) { 15574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe for (Monitor* mon : *monitors) { 15674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe ReleaseMonitorToPool(self, mon); 15774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe } 158ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers} 159ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers 160ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers} // namespace art 161