diff options
author | 2016-03-10 08:33:45 -0800 | |
---|---|---|
committer | 2016-03-10 12:03:55 -0800 | |
commit | 057134bdf40981555a8bf56ab8d703a503b40f8f (patch) | |
tree | 2c58f5bcb68b6b3517eeab67d8be0b3cd5f45362 | |
parent | 93e46b2a14050d8f65088ccb44d6fab6c1c46b2c (diff) |
ART: Release all resource on MonitorPool destruction
To be valgrind-clean, we need to release the current metadata and
all chunks on destruction.
Bug: 27156726
Change-Id: Ia51cea139a6e9669975b6ac045f5223cd68f1f6a
-rw-r--r-- | runtime/monitor_pool.cc | 24 | ||||
-rw-r--r-- | runtime/monitor_pool.h | 10 |
2 files changed, 32 insertions, 2 deletions
diff --git a/runtime/monitor_pool.cc b/runtime/monitor_pool.cc index 9e78cda190..ce38e4f108 100644 --- a/runtime/monitor_pool.cc +++ b/runtime/monitor_pool.cc @@ -42,11 +42,12 @@ void MonitorPool::AllocateChunk() { if (capacity_ == 0U) { // Initialization. capacity_ = kInitialChunkStorage; - uintptr_t* new_backing = new uintptr_t[capacity_]; + uintptr_t* new_backing = new uintptr_t[capacity_](); + DCHECK(monitor_chunks_.LoadRelaxed() == nullptr); monitor_chunks_.StoreRelaxed(new_backing); } else { size_t new_capacity = 2 * capacity_; - uintptr_t* new_backing = new uintptr_t[new_capacity]; + uintptr_t* new_backing = new uintptr_t[new_capacity](); uintptr_t* old_backing = monitor_chunks_.LoadRelaxed(); memcpy(new_backing, old_backing, sizeof(uintptr_t) * capacity_); monitor_chunks_.StoreRelaxed(new_backing); @@ -88,6 +89,25 @@ void MonitorPool::AllocateChunk() { first_free_ = last; } +void MonitorPool::FreeInternal() { + // This is on shutdown with NO_THREAD_SAFETY_ANALYSIS, can't/don't need to lock. + uintptr_t* backing = monitor_chunks_.LoadRelaxed(); + DCHECK(backing != nullptr); + DCHECK_GT(capacity_, 0U); + DCHECK_GT(num_chunks_, 0U); + + for (size_t i = 0; i < capacity_; ++i) { + if (i < num_chunks_) { + DCHECK_NE(backing[i], 0U); + allocator_.deallocate(reinterpret_cast<uint8_t*>(backing[i]), kChunkSize); + } else { + DCHECK_EQ(backing[i], 0U); + } + } + + delete[] backing; +} + Monitor* MonitorPool::CreateMonitorInPool(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code) SHARED_REQUIRES(Locks::mutator_lock_) { diff --git a/runtime/monitor_pool.h b/runtime/monitor_pool.h index de553fc99b..875b3fe73d 100644 --- a/runtime/monitor_pool.h +++ b/runtime/monitor_pool.h @@ -104,6 +104,12 @@ class MonitorPool { #endif } + ~MonitorPool() { +#ifdef __LP64__ + FreeInternal(); +#endif + } + private: #ifdef __LP64__ // When we create a monitor pool, threads have not been initialized, yet, so ignore thread-safety @@ -112,6 +118,10 @@ class MonitorPool { void AllocateChunk() REQUIRES(Locks::allocated_monitor_ids_lock_); + // Release all chunks and metadata. This is done on shutdown, where threads have been destroyed, + // so ignore thead-safety analysis. + void FreeInternal() NO_THREAD_SAFETY_ANALYSIS; + Monitor* CreateMonitorInPool(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code) SHARED_REQUIRES(Locks::mutator_lock_); |