xref: /aosp_15_r20/system/unwinding/libunwindstack/MemoryCache.h (revision eb293b8f56ee8303637c5595cfcdeef8039e85c6)
1*eb293b8fSAndroid Build Coastguard Worker /*
2*eb293b8fSAndroid Build Coastguard Worker  * Copyright (C) 2019 The Android Open Source Project
3*eb293b8fSAndroid Build Coastguard Worker  *
4*eb293b8fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*eb293b8fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*eb293b8fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*eb293b8fSAndroid Build Coastguard Worker  *
8*eb293b8fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*eb293b8fSAndroid Build Coastguard Worker  *
10*eb293b8fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*eb293b8fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*eb293b8fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*eb293b8fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*eb293b8fSAndroid Build Coastguard Worker  * limitations under the License.
15*eb293b8fSAndroid Build Coastguard Worker  */
16*eb293b8fSAndroid Build Coastguard Worker 
17*eb293b8fSAndroid Build Coastguard Worker #pragma once
18*eb293b8fSAndroid Build Coastguard Worker 
19*eb293b8fSAndroid Build Coastguard Worker #include <pthread.h>
20*eb293b8fSAndroid Build Coastguard Worker #include <stdint.h>
21*eb293b8fSAndroid Build Coastguard Worker 
22*eb293b8fSAndroid Build Coastguard Worker #include <memory>
23*eb293b8fSAndroid Build Coastguard Worker #include <mutex>
24*eb293b8fSAndroid Build Coastguard Worker #include <optional>
25*eb293b8fSAndroid Build Coastguard Worker #include <unordered_map>
26*eb293b8fSAndroid Build Coastguard Worker 
27*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Memory.h>
28*eb293b8fSAndroid Build Coastguard Worker 
29*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack {
30*eb293b8fSAndroid Build Coastguard Worker 
31*eb293b8fSAndroid Build Coastguard Worker class MemoryCacheBase : public Memory {
32*eb293b8fSAndroid Build Coastguard Worker  public:
MemoryCacheBase(Memory * memory)33*eb293b8fSAndroid Build Coastguard Worker   MemoryCacheBase(Memory* memory) : impl_(memory) {}
34*eb293b8fSAndroid Build Coastguard Worker   virtual ~MemoryCacheBase() = default;
35*eb293b8fSAndroid Build Coastguard Worker 
AsMemoryCacheBase()36*eb293b8fSAndroid Build Coastguard Worker   MemoryCacheBase* AsMemoryCacheBase() override { return this; }
37*eb293b8fSAndroid Build Coastguard Worker 
UnderlyingMemory()38*eb293b8fSAndroid Build Coastguard Worker   const std::shared_ptr<Memory>& UnderlyingMemory() { return impl_; }
39*eb293b8fSAndroid Build Coastguard Worker 
Read(uint64_t addr,void * dst,size_t size)40*eb293b8fSAndroid Build Coastguard Worker   size_t Read(uint64_t addr, void* dst, size_t size) override {
41*eb293b8fSAndroid Build Coastguard Worker     // Only look at the cache for small reads.
42*eb293b8fSAndroid Build Coastguard Worker     if (size > 64) {
43*eb293b8fSAndroid Build Coastguard Worker       return impl_->Read(addr, dst, size);
44*eb293b8fSAndroid Build Coastguard Worker     }
45*eb293b8fSAndroid Build Coastguard Worker     return CachedRead(addr, dst, size);
46*eb293b8fSAndroid Build Coastguard Worker   }
47*eb293b8fSAndroid Build Coastguard Worker 
ReadTag(uint64_t addr)48*eb293b8fSAndroid Build Coastguard Worker   long ReadTag(uint64_t addr) override { return impl_->ReadTag(addr); }
49*eb293b8fSAndroid Build Coastguard Worker 
50*eb293b8fSAndroid Build Coastguard Worker  protected:
51*eb293b8fSAndroid Build Coastguard Worker   constexpr static size_t kCacheBits = 12;
52*eb293b8fSAndroid Build Coastguard Worker   constexpr static size_t kCacheMask = (1 << kCacheBits) - 1;
53*eb293b8fSAndroid Build Coastguard Worker   constexpr static size_t kCacheSize = 1 << kCacheBits;
54*eb293b8fSAndroid Build Coastguard Worker 
55*eb293b8fSAndroid Build Coastguard Worker   using CacheDataType = std::unordered_map<uint64_t, uint8_t[kCacheSize]>;
56*eb293b8fSAndroid Build Coastguard Worker 
57*eb293b8fSAndroid Build Coastguard Worker   virtual size_t CachedRead(uint64_t addr, void* dst, size_t size) = 0;
58*eb293b8fSAndroid Build Coastguard Worker 
59*eb293b8fSAndroid Build Coastguard Worker   size_t InternalCachedRead(uint64_t addr, void* dst, size_t size, CacheDataType* cache);
60*eb293b8fSAndroid Build Coastguard Worker 
61*eb293b8fSAndroid Build Coastguard Worker   std::shared_ptr<Memory> impl_;
62*eb293b8fSAndroid Build Coastguard Worker };
63*eb293b8fSAndroid Build Coastguard Worker 
64*eb293b8fSAndroid Build Coastguard Worker class MemoryCache : public MemoryCacheBase {
65*eb293b8fSAndroid Build Coastguard Worker  public:
MemoryCache(Memory * memory)66*eb293b8fSAndroid Build Coastguard Worker   MemoryCache(Memory* memory) : MemoryCacheBase(memory) {}
67*eb293b8fSAndroid Build Coastguard Worker   virtual ~MemoryCache() = default;
68*eb293b8fSAndroid Build Coastguard Worker 
69*eb293b8fSAndroid Build Coastguard Worker   size_t CachedRead(uint64_t addr, void* dst, size_t size) override;
70*eb293b8fSAndroid Build Coastguard Worker 
71*eb293b8fSAndroid Build Coastguard Worker   void Clear() override;
72*eb293b8fSAndroid Build Coastguard Worker 
73*eb293b8fSAndroid Build Coastguard Worker  protected:
74*eb293b8fSAndroid Build Coastguard Worker   CacheDataType cache_;
75*eb293b8fSAndroid Build Coastguard Worker 
76*eb293b8fSAndroid Build Coastguard Worker   std::mutex cache_lock_;
77*eb293b8fSAndroid Build Coastguard Worker };
78*eb293b8fSAndroid Build Coastguard Worker 
79*eb293b8fSAndroid Build Coastguard Worker class MemoryThreadCache : public MemoryCacheBase {
80*eb293b8fSAndroid Build Coastguard Worker  public:
81*eb293b8fSAndroid Build Coastguard Worker   MemoryThreadCache(Memory* memory);
82*eb293b8fSAndroid Build Coastguard Worker   virtual ~MemoryThreadCache();
83*eb293b8fSAndroid Build Coastguard Worker 
84*eb293b8fSAndroid Build Coastguard Worker   size_t CachedRead(uint64_t addr, void* dst, size_t size) override;
85*eb293b8fSAndroid Build Coastguard Worker 
86*eb293b8fSAndroid Build Coastguard Worker   void Clear() override;
87*eb293b8fSAndroid Build Coastguard Worker 
88*eb293b8fSAndroid Build Coastguard Worker  protected:
89*eb293b8fSAndroid Build Coastguard Worker   std::optional<pthread_key_t> thread_cache_;
90*eb293b8fSAndroid Build Coastguard Worker };
91*eb293b8fSAndroid Build Coastguard Worker 
92*eb293b8fSAndroid Build Coastguard Worker }  // namespace unwindstack
93