monitor_pool.h revision 13735955f39b3b304c37d2b2840663c131262c18
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__
4874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    return new Monitor(self, owner, obj, hash_code);
4974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe#else
5074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    return GetMonitorPool()->CreateMonitorInPool(self, owner, obj, hash_code);
5174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe#endif
5274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  }
5374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe
5474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  static void ReleaseMonitor(Thread* self, Monitor* monitor) {
5574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe#ifndef __LP64__
5674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    delete monitor;
5774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe#else
5874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    GetMonitorPool()->ReleaseMonitorToPool(self, monitor);
5974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe#endif
6074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  }
6174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe
62bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  static void ReleaseMonitors(Thread* self, MonitorList::Monitors* monitors) {
6374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe#ifndef __LP64__
6474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    STLDeleteElements(monitors);
6574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe#else
6674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    GetMonitorPool()->ReleaseMonitorsToPool(self, monitors);
6774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe#endif
6874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  }
6974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe
70ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  static Monitor* MonitorFromMonitorId(MonitorId mon_id) {
71ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#ifndef __LP64__
72ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    return reinterpret_cast<Monitor*>(mon_id << 3);
73ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#else
7474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    return GetMonitorPool()->LookupMonitor(mon_id);
75ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#endif
76ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  }
77ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers
78ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  static MonitorId MonitorIdFromMonitor(Monitor* mon) {
79ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#ifndef __LP64__
80ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    return reinterpret_cast<MonitorId>(mon) >> 3;
81ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#else
82ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    return mon->GetMonitorId();
83ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#endif
84ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  }
85ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers
8674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  static MonitorId ComputeMonitorId(Monitor* mon, Thread* self) {
87ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#ifndef __LP64__
88ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    return MonitorIdFromMonitor(mon);
89ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#else
9074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    return GetMonitorPool()->ComputeMonitorIdInPool(mon, self);
91ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#endif
92ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  }
93ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers
9474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  static MonitorPool* GetMonitorPool() {
95ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#ifndef __LP64__
9674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    return nullptr;
97ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#else
9874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    return Runtime::Current()->GetMonitorPool();
99ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#endif
100ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  }
101ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers
102ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers private:
103ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#ifdef __LP64__
10474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  // When we create a monitor pool, threads have not been initialized, yet, so ignore thread-safety
10574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  // analysis.
10674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  MonitorPool() NO_THREAD_SAFETY_ANALYSIS;
107ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers
10874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  void AllocateChunk() EXCLUSIVE_LOCKS_REQUIRED(Locks::allocated_monitor_ids_lock_);
109ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers
11074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  Monitor* CreateMonitorInPool(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code)
11174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
112ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers
11374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  void ReleaseMonitorToPool(Thread* self, Monitor* monitor);
114bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  void ReleaseMonitorsToPool(Thread* self, MonitorList::Monitors* monitors);
115ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers
11674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  // Note: This is safe as we do not ever move chunks.
11774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  Monitor* LookupMonitor(MonitorId mon_id) {
11874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    size_t offset = MonitorIdToOffset(mon_id);
11974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    size_t index = offset / kChunkSize;
12074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    size_t offset_in_chunk = offset % kChunkSize;
12174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    uintptr_t base = *(monitor_chunks_.LoadRelaxed()+index);
12274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    return reinterpret_cast<Monitor*>(base + offset_in_chunk);
12374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  }
12474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe
12574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  static bool IsInChunk(uintptr_t base_addr, Monitor* mon) {
12674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    uintptr_t mon_ptr = reinterpret_cast<uintptr_t>(mon);
12774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    return base_addr <= mon_ptr && (mon_ptr - base_addr < kChunkSize);
12874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  }
12974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe
13074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  // Note: This is safe as we do not ever move chunks.
13174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  MonitorId ComputeMonitorIdInPool(Monitor* mon, Thread* self) {
13274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    MutexLock mu(self, *Locks::allocated_monitor_ids_lock_);
13374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    for (size_t index = 0; index < num_chunks_; ++index) {
13474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe      uintptr_t chunk_addr = *(monitor_chunks_.LoadRelaxed() + index);
13574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe      if (IsInChunk(chunk_addr, mon)) {
13674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe        return OffsetToMonitorId(reinterpret_cast<uintptr_t>(mon) - chunk_addr + index * kChunkSize);
13774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe      }
13874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    }
13974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    LOG(FATAL) << "Did not find chunk that contains monitor.";
14074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    return 0;
14174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  }
14274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe
14374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  static size_t MonitorIdToOffset(MonitorId id) {
14474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    return id << 3;
14574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  }
14674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe
14774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  static MonitorId OffsetToMonitorId(size_t offset) {
14874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe    return static_cast<MonitorId>(offset >> 3);
14974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  }
150ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers
15174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  // TODO: There are assumptions in the code that monitor addresses are 8B aligned (>>3).
15274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  static constexpr size_t kMonitorAlignment = 8;
15374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  // Size of a monitor, rounded up to a multiple of alignment.
15474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  static constexpr size_t kAlignedMonitorSize = (sizeof(Monitor) + kMonitorAlignment - 1) &
15574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe                                                -kMonitorAlignment;
15674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  // As close to a page as we can get seems a good start.
15774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  static constexpr size_t kChunkCapacity = kPageSize / kAlignedMonitorSize;
15874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  // Chunk size that is referenced in the id. We can collapse this to the actually used storage
15974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  // in a chunk, i.e., kChunkCapacity * kAlignedMonitorSize, but this will mean proper divisions.
16074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  static constexpr size_t kChunkSize = kPageSize;
16174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  // The number of initial chunks storable in monitor_chunks_. The number is large enough to make
16274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  // resizing unlikely, but small enough to not waste too much memory.
16374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  static constexpr size_t kInitialChunkStorage = 8U;
16474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe
16574240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  // List of memory chunks. Each chunk is kChunkSize.
16674240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  Atomic<uintptr_t*> monitor_chunks_;
16774240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  // Number of chunks stored.
16874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  size_t num_chunks_ GUARDED_BY(Locks::allocated_monitor_ids_lock_);
16974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  // Number of chunks storable.
17074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  size_t capacity_ GUARDED_BY(Locks::allocated_monitor_ids_lock_);
17174240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe
17274240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  // To avoid race issues when resizing, we keep all the previous arrays.
17374240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  std::vector<uintptr_t*> old_chunk_arrays_ GUARDED_BY(Locks::allocated_monitor_ids_lock_);
17474240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe
17513735955f39b3b304c37d2b2840663c131262c18Ian Rogers  typedef TrackingAllocator<uint8_t, kAllocatorTagMonitorPool> Allocator;
176bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier  Allocator allocator_;
177bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier
17874240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  // Start of free list of monitors.
17974240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  // Note: these point to the right memory regions, but do *not* denote initialized objects.
18074240819ae09e29b2753ef38f4eb4be1c2762e2eAndreas Gampe  Monitor* first_free_ GUARDED_BY(Locks::allocated_monitor_ids_lock_);
181ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#endif
182ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers};
183ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers
184ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers}  // namespace art
185ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers
186ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#endif  // ART_RUNTIME_MONITOR_POOL_H_
187