1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #pragma once 17 18 #include "aemu/base/containers/Lookup.h" 19 #include "aemu/base/files/Stream.h" 20 #include "aemu/base/files/StreamSerializing.h" 21 #include "aemu/base/synchronization/Lock.h" 22 #include "aemu/base/Compiler.h" 23 24 #include <algorithm> 25 #include <cstdint> 26 #include <unordered_map> 27 28 namespace gfxstream { 29 30 // The purpose of StalePtrRegistry is to track integers corresponding to 31 // host-side pointers that may be invalidated after snapshots. 32 template <class T> 33 class StalePtrRegistry { 34 public: 35 StalePtrRegistry() = default; 36 addPtr(T * ptr)37 void addPtr(T* ptr) { 38 android::base::AutoWriteLock lock(mLock); 39 mPtrs[asHandle(ptr)] = { ptr, Staleness::Live }; 40 } 41 removePtr(T * ptr)42 void removePtr(T* ptr) { 43 android::base::AutoWriteLock lock(mLock); 44 uint64_t handle = asHandle(ptr); 45 mPtrs.erase(handle); 46 } 47 remapStalePtr(uint64_t handle,T * newptr)48 void remapStalePtr(uint64_t handle, T* newptr) { 49 android::base::AutoWriteLock lock(mLock); 50 mPtrs[handle] = { newptr, Staleness::PrevSnapshot }; 51 } 52 53 T* getPtr(uint64_t handle, T* defaultPtr = nullptr, 54 bool removeFromStaleOnGet = false) { 55 android::base::AutoReadLock lock(mLock); 56 57 // return |defaultPtr| if not found. 58 T* res = defaultPtr; 59 60 Entry* it = nullptr; 61 62 if ((it = android::base::find(mPtrs, handle))) 63 res = it->ptr; 64 65 if (removeFromStaleOnGet && 66 it && it->staleness == Staleness::PrevSnapshot) { 67 lock.unlockRead(); 68 android::base::AutoWriteLock wrlock(mLock); 69 mPtrs.erase(handle); 70 } 71 72 return res; 73 } 74 makeCurrentPtrsStale()75 void makeCurrentPtrsStale() { 76 android::base::AutoWriteLock lock(mLock); 77 for (auto& it : mPtrs) { 78 it.second.staleness = 79 Staleness::PrevSnapshot; 80 } 81 } 82 numCurrEntries()83 size_t numCurrEntries() const { 84 return countWithStaleness(Staleness::Live); 85 } 86 numStaleEntries()87 size_t numStaleEntries() const { 88 return countWithStaleness(Staleness::PrevSnapshot); 89 } 90 onSave(android::base::Stream * stream)91 void onSave(android::base::Stream* stream) { 92 android::base::AutoReadLock lock(mLock); 93 saveCollection( 94 stream, mPtrs, 95 [](android::base::Stream* stream, 96 const std::pair<uint64_t, Entry>& entry) { 97 stream->putBe64(entry.first); 98 }); 99 } 100 onLoad(android::base::Stream * stream)101 void onLoad(android::base::Stream* stream) { 102 android::base::AutoWriteLock lock(mLock); 103 loadCollection( 104 stream, &mPtrs, 105 [](android::base::Stream* stream) { 106 uint64_t handle = stream->getBe64(); 107 return std::make_pair( 108 handle, 109 (Entry){ nullptr, Staleness::PrevSnapshot }); 110 }); 111 } 112 private: asHandle(const T * ptr)113 static uint64_t asHandle(const T* ptr) { 114 return (uint64_t)(uintptr_t)ptr; 115 } 116 asPtr(uint64_t handle)117 static T* asPtr(uint64_t handle) { 118 return (T*)(uintptr_t)handle; 119 } 120 121 enum class Staleness { 122 Live, 123 PrevSnapshot, 124 }; 125 struct Entry { 126 T* ptr; 127 Staleness staleness; 128 }; 129 130 using PtrMap = std::unordered_map<uint64_t, Entry>; 131 countWithStaleness(Staleness check)132 size_t countWithStaleness(Staleness check) const { 133 android::base::AutoReadLock lock(mLock); 134 return std::count_if(mPtrs.begin(), mPtrs.end(), 135 [check](const typename PtrMap::value_type& entry) { 136 return entry.second.staleness == check; 137 }); 138 } 139 140 mutable android::base::ReadWriteLock mLock; 141 PtrMap mPtrs; 142 143 DISALLOW_COPY_AND_ASSIGN(StalePtrRegistry); 144 }; 145 146 } // namespace gfxstream 147