1d495c534SGreg Clayton //===-- Memory.cpp ----------------------------------------------*- C++ -*-===// 2d495c534SGreg Clayton // 3d495c534SGreg Clayton // The LLVM Compiler Infrastructure 4d495c534SGreg Clayton // 5d495c534SGreg Clayton // This file is distributed under the University of Illinois Open Source 6d495c534SGreg Clayton // License. See LICENSE.TXT for details. 7d495c534SGreg Clayton // 8d495c534SGreg Clayton //===----------------------------------------------------------------------===// 9d495c534SGreg Clayton 10d495c534SGreg Clayton #include "lldb/Target/Memory.h" 11d495c534SGreg Clayton // C Includes 12ffeba256SVirgile Bello #include <inttypes.h> 13d495c534SGreg Clayton // C++ Includes 14d495c534SGreg Clayton // Other libraries and framework includes 15d495c534SGreg Clayton // Project includes 16d495c534SGreg Clayton #include "lldb/Core/DataBufferHeap.h" 17d495c534SGreg Clayton #include "lldb/Core/State.h" 18d495c534SGreg Clayton #include "lldb/Core/Log.h" 19d495c534SGreg Clayton #include "lldb/Target/Process.h" 20d495c534SGreg Clayton 21d495c534SGreg Clayton using namespace lldb; 22d495c534SGreg Clayton using namespace lldb_private; 23d495c534SGreg Clayton 24d495c534SGreg Clayton //---------------------------------------------------------------------- 25d495c534SGreg Clayton // MemoryCache constructor 26d495c534SGreg Clayton //---------------------------------------------------------------------- 27d495c534SGreg Clayton MemoryCache::MemoryCache(Process &process) : 28d495c534SGreg Clayton m_process (process), 29*f0340c9aSJason Molenda m_cache_line_byte_size (process.GetMemoryCacheLineSize()), 30a9f40ad8SGreg Clayton m_mutex (Mutex::eMutexTypeRecursive), 31a9f40ad8SGreg Clayton m_cache (), 32a9f40ad8SGreg Clayton m_invalid_ranges () 33d495c534SGreg Clayton { 34d495c534SGreg Clayton } 35d495c534SGreg Clayton 36d495c534SGreg Clayton //---------------------------------------------------------------------- 37d495c534SGreg Clayton // Destructor 38d495c534SGreg Clayton //---------------------------------------------------------------------- 39d495c534SGreg Clayton MemoryCache::~MemoryCache() 40d495c534SGreg Clayton { 41d495c534SGreg Clayton } 42d495c534SGreg Clayton 43d495c534SGreg Clayton void 4415fc2be7SGreg Clayton MemoryCache::Clear(bool clear_invalid_ranges) 45d495c534SGreg Clayton { 46a9f40ad8SGreg Clayton Mutex::Locker locker (m_mutex); 47d495c534SGreg Clayton m_cache.clear(); 4815fc2be7SGreg Clayton if (clear_invalid_ranges) 4915fc2be7SGreg Clayton m_invalid_ranges.Clear(); 50*f0340c9aSJason Molenda m_cache_line_byte_size = m_process.GetMemoryCacheLineSize(); 51d495c534SGreg Clayton } 52d495c534SGreg Clayton 53d495c534SGreg Clayton void 54d495c534SGreg Clayton MemoryCache::Flush (addr_t addr, size_t size) 55d495c534SGreg Clayton { 56d495c534SGreg Clayton if (size == 0) 57d495c534SGreg Clayton return; 58d495c534SGreg Clayton 59a9f40ad8SGreg Clayton Mutex::Locker locker (m_mutex); 60d495c534SGreg Clayton if (m_cache.empty()) 61d495c534SGreg Clayton return; 62d495c534SGreg Clayton 63de0e9d04SGreg Clayton const uint32_t cache_line_byte_size = m_cache_line_byte_size; 64de0e9d04SGreg Clayton const addr_t end_addr = (addr + size - 1); 65de0e9d04SGreg Clayton const addr_t first_cache_line_addr = addr - (addr % cache_line_byte_size); 66de0e9d04SGreg Clayton const addr_t last_cache_line_addr = end_addr - (end_addr % cache_line_byte_size); 67de0e9d04SGreg Clayton // Watch for overflow where size will cause us to go off the end of the 68de0e9d04SGreg Clayton // 64 bit address space 69de0e9d04SGreg Clayton uint32_t num_cache_lines; 70de0e9d04SGreg Clayton if (last_cache_line_addr >= first_cache_line_addr) 71de0e9d04SGreg Clayton num_cache_lines = ((last_cache_line_addr - first_cache_line_addr)/cache_line_byte_size) + 1; 72de0e9d04SGreg Clayton else 73de0e9d04SGreg Clayton num_cache_lines = (UINT64_MAX - first_cache_line_addr + 1)/cache_line_byte_size; 74d495c534SGreg Clayton 75de0e9d04SGreg Clayton uint32_t cache_idx = 0; 76de0e9d04SGreg Clayton for (addr_t curr_addr = first_cache_line_addr; 77de0e9d04SGreg Clayton cache_idx < num_cache_lines; 78de0e9d04SGreg Clayton curr_addr += cache_line_byte_size, ++cache_idx) 79d495c534SGreg Clayton { 80a9f40ad8SGreg Clayton BlockMap::iterator pos = m_cache.find (curr_addr); 81d495c534SGreg Clayton if (pos != m_cache.end()) 82d495c534SGreg Clayton m_cache.erase(pos); 83d495c534SGreg Clayton } 84d495c534SGreg Clayton } 85d495c534SGreg Clayton 86a9f40ad8SGreg Clayton void 87a9f40ad8SGreg Clayton MemoryCache::AddInvalidRange (lldb::addr_t base_addr, lldb::addr_t byte_size) 88a9f40ad8SGreg Clayton { 89a9f40ad8SGreg Clayton if (byte_size > 0) 90a9f40ad8SGreg Clayton { 91a9f40ad8SGreg Clayton Mutex::Locker locker (m_mutex); 92a9f40ad8SGreg Clayton InvalidRanges::Entry range (base_addr, byte_size); 93a9f40ad8SGreg Clayton m_invalid_ranges.Append(range); 94a9f40ad8SGreg Clayton m_invalid_ranges.Sort(); 95a9f40ad8SGreg Clayton } 96a9f40ad8SGreg Clayton } 97a9f40ad8SGreg Clayton 98a9f40ad8SGreg Clayton bool 99a9f40ad8SGreg Clayton MemoryCache::RemoveInvalidRange (lldb::addr_t base_addr, lldb::addr_t byte_size) 100a9f40ad8SGreg Clayton { 101a9f40ad8SGreg Clayton if (byte_size > 0) 102a9f40ad8SGreg Clayton { 103a9f40ad8SGreg Clayton Mutex::Locker locker (m_mutex); 104a9f40ad8SGreg Clayton const uint32_t idx = m_invalid_ranges.FindEntryIndexThatContains(base_addr); 105a9f40ad8SGreg Clayton if (idx != UINT32_MAX) 106a9f40ad8SGreg Clayton { 107a9f40ad8SGreg Clayton const InvalidRanges::Entry *entry = m_invalid_ranges.GetEntryAtIndex (idx); 108a9f40ad8SGreg Clayton if (entry->GetRangeBase() == base_addr && entry->GetByteSize() == byte_size) 109a9f40ad8SGreg Clayton return m_invalid_ranges.RemoveEntrtAtIndex (idx); 110a9f40ad8SGreg Clayton } 111a9f40ad8SGreg Clayton } 112a9f40ad8SGreg Clayton return false; 113a9f40ad8SGreg Clayton } 114a9f40ad8SGreg Clayton 115a9f40ad8SGreg Clayton 116a9f40ad8SGreg Clayton 117d495c534SGreg Clayton size_t 118d495c534SGreg Clayton MemoryCache::Read (addr_t addr, 119d495c534SGreg Clayton void *dst, 120d495c534SGreg Clayton size_t dst_len, 121d495c534SGreg Clayton Error &error) 122d495c534SGreg Clayton { 123d495c534SGreg Clayton size_t bytes_left = dst_len; 1246076bf4eSJason Molenda 1256076bf4eSJason Molenda // If this memory read request is larger than the cache line size, then 1266076bf4eSJason Molenda // we (1) try to read as much of it at once as possible, and (2) don't 1276076bf4eSJason Molenda // add the data to the memory cache. We don't want to split a big read 1286076bf4eSJason Molenda // up into more separate reads than necessary, and with a large memory read 1296076bf4eSJason Molenda // request, it is unlikely that the caller function will ask for the next 1306076bf4eSJason Molenda // 4 bytes after the large memory read - so there's little benefit to saving 1316076bf4eSJason Molenda // it in the cache. 1326076bf4eSJason Molenda if (dst && dst_len > m_cache_line_byte_size) 1336076bf4eSJason Molenda { 1346076bf4eSJason Molenda return m_process.ReadMemoryFromInferior (addr, dst, dst_len, error); 1356076bf4eSJason Molenda } 1366076bf4eSJason Molenda 137d495c534SGreg Clayton if (dst && bytes_left > 0) 138d495c534SGreg Clayton { 139d495c534SGreg Clayton const uint32_t cache_line_byte_size = m_cache_line_byte_size; 140d495c534SGreg Clayton uint8_t *dst_buf = (uint8_t *)dst; 141d495c534SGreg Clayton addr_t curr_addr = addr - (addr % cache_line_byte_size); 142d495c534SGreg Clayton addr_t cache_offset = addr - curr_addr; 143a9f40ad8SGreg Clayton Mutex::Locker locker (m_mutex); 144d495c534SGreg Clayton 145d495c534SGreg Clayton while (bytes_left > 0) 146d495c534SGreg Clayton { 147a9f40ad8SGreg Clayton if (m_invalid_ranges.FindEntryThatContains(curr_addr)) 14855d24311SJim Ingham { 14955d24311SJim Ingham error.SetErrorStringWithFormat("memory read failed for 0x%" PRIx64, curr_addr); 150a9f40ad8SGreg Clayton return dst_len - bytes_left; 15155d24311SJim Ingham } 152a9f40ad8SGreg Clayton 153a9f40ad8SGreg Clayton BlockMap::const_iterator pos = m_cache.find (curr_addr); 154a9f40ad8SGreg Clayton BlockMap::const_iterator end = m_cache.end (); 155d495c534SGreg Clayton 156d495c534SGreg Clayton if (pos != end) 157d495c534SGreg Clayton { 158d495c534SGreg Clayton size_t curr_read_size = cache_line_byte_size - cache_offset; 159d495c534SGreg Clayton if (curr_read_size > bytes_left) 160d495c534SGreg Clayton curr_read_size = bytes_left; 161d495c534SGreg Clayton 162d495c534SGreg Clayton memcpy (dst_buf + dst_len - bytes_left, pos->second->GetBytes() + cache_offset, curr_read_size); 163d495c534SGreg Clayton 164d495c534SGreg Clayton bytes_left -= curr_read_size; 165d495c534SGreg Clayton curr_addr += curr_read_size + cache_offset; 166d495c534SGreg Clayton cache_offset = 0; 167d495c534SGreg Clayton 168d495c534SGreg Clayton if (bytes_left > 0) 169d495c534SGreg Clayton { 170d495c534SGreg Clayton // Get sequential cache page hits 171d495c534SGreg Clayton for (++pos; (pos != end) && (bytes_left > 0); ++pos) 172d495c534SGreg Clayton { 173d495c534SGreg Clayton assert ((curr_addr % cache_line_byte_size) == 0); 174d495c534SGreg Clayton 175d495c534SGreg Clayton if (pos->first != curr_addr) 176d495c534SGreg Clayton break; 177d495c534SGreg Clayton 178d495c534SGreg Clayton curr_read_size = pos->second->GetByteSize(); 179d495c534SGreg Clayton if (curr_read_size > bytes_left) 180d495c534SGreg Clayton curr_read_size = bytes_left; 181d495c534SGreg Clayton 182d495c534SGreg Clayton memcpy (dst_buf + dst_len - bytes_left, pos->second->GetBytes(), curr_read_size); 183d495c534SGreg Clayton 184d495c534SGreg Clayton bytes_left -= curr_read_size; 185d495c534SGreg Clayton curr_addr += curr_read_size; 186d495c534SGreg Clayton 187d495c534SGreg Clayton // We have a cache page that succeeded to read some bytes 188d495c534SGreg Clayton // but not an entire page. If this happens, we must cap 189d495c534SGreg Clayton // off how much data we are able to read... 190d495c534SGreg Clayton if (pos->second->GetByteSize() != cache_line_byte_size) 191d495c534SGreg Clayton return dst_len - bytes_left; 192d495c534SGreg Clayton } 193d495c534SGreg Clayton } 194d495c534SGreg Clayton } 195d495c534SGreg Clayton 196d495c534SGreg Clayton // We need to read from the process 197d495c534SGreg Clayton 198d495c534SGreg Clayton if (bytes_left > 0) 199d495c534SGreg Clayton { 200d495c534SGreg Clayton assert ((curr_addr % cache_line_byte_size) == 0); 2017b0992d9SGreg Clayton std::unique_ptr<DataBufferHeap> data_buffer_heap_ap(new DataBufferHeap (cache_line_byte_size, 0)); 202d495c534SGreg Clayton size_t process_bytes_read = m_process.ReadMemoryFromInferior (curr_addr, 203d495c534SGreg Clayton data_buffer_heap_ap->GetBytes(), 204d495c534SGreg Clayton data_buffer_heap_ap->GetByteSize(), 205d495c534SGreg Clayton error); 206d495c534SGreg Clayton if (process_bytes_read == 0) 207d495c534SGreg Clayton return dst_len - bytes_left; 208d495c534SGreg Clayton 209d495c534SGreg Clayton if (process_bytes_read != cache_line_byte_size) 210d495c534SGreg Clayton data_buffer_heap_ap->SetByteSize (process_bytes_read); 211d495c534SGreg Clayton m_cache[curr_addr] = DataBufferSP (data_buffer_heap_ap.release()); 212d495c534SGreg Clayton // We have read data and put it into the cache, continue through the 213d495c534SGreg Clayton // loop again to get the data out of the cache... 214d495c534SGreg Clayton } 215d495c534SGreg Clayton } 216d495c534SGreg Clayton } 217d495c534SGreg Clayton 218d495c534SGreg Clayton return dst_len - bytes_left; 219d495c534SGreg Clayton } 220d495c534SGreg Clayton 221d495c534SGreg Clayton 222d495c534SGreg Clayton 223d495c534SGreg Clayton AllocatedBlock::AllocatedBlock (lldb::addr_t addr, 224d495c534SGreg Clayton uint32_t byte_size, 225d495c534SGreg Clayton uint32_t permissions, 226d495c534SGreg Clayton uint32_t chunk_size) : 227d495c534SGreg Clayton m_addr (addr), 228d495c534SGreg Clayton m_byte_size (byte_size), 229d495c534SGreg Clayton m_permissions (permissions), 230d495c534SGreg Clayton m_chunk_size (chunk_size), 231d495c534SGreg Clayton m_offset_to_chunk_size () 232d495c534SGreg Clayton // m_allocated (byte_size / chunk_size) 233d495c534SGreg Clayton { 234d495c534SGreg Clayton assert (byte_size > chunk_size); 235d495c534SGreg Clayton } 236d495c534SGreg Clayton 237d495c534SGreg Clayton AllocatedBlock::~AllocatedBlock () 238d495c534SGreg Clayton { 239d495c534SGreg Clayton } 240d495c534SGreg Clayton 241d495c534SGreg Clayton lldb::addr_t 242d495c534SGreg Clayton AllocatedBlock::ReserveBlock (uint32_t size) 243d495c534SGreg Clayton { 244d495c534SGreg Clayton addr_t addr = LLDB_INVALID_ADDRESS; 245e7701feeSJim Ingham Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); 246d495c534SGreg Clayton if (size <= m_byte_size) 247d495c534SGreg Clayton { 248d495c534SGreg Clayton const uint32_t needed_chunks = CalculateChunksNeededForSize (size); 249d495c534SGreg Clayton 250d495c534SGreg Clayton if (m_offset_to_chunk_size.empty()) 251d495c534SGreg Clayton { 252d495c534SGreg Clayton m_offset_to_chunk_size[0] = needed_chunks; 253d495c534SGreg Clayton if (log) 254e7701feeSJim Ingham log->Printf ("[1] AllocatedBlock::ReserveBlock(%p) (size = %u (0x%x)) => offset = 0x%x, %u %u bit chunks", this, size, size, 0, needed_chunks, m_chunk_size); 255d495c534SGreg Clayton addr = m_addr; 256d495c534SGreg Clayton } 257d495c534SGreg Clayton else 258d495c534SGreg Clayton { 259d495c534SGreg Clayton uint32_t last_offset = 0; 260d495c534SGreg Clayton OffsetToChunkSize::const_iterator pos = m_offset_to_chunk_size.begin(); 261d495c534SGreg Clayton OffsetToChunkSize::const_iterator end = m_offset_to_chunk_size.end(); 262d495c534SGreg Clayton while (pos != end) 263d495c534SGreg Clayton { 264d495c534SGreg Clayton if (pos->first > last_offset) 265d495c534SGreg Clayton { 266d495c534SGreg Clayton const uint32_t bytes_available = pos->first - last_offset; 267d495c534SGreg Clayton const uint32_t num_chunks = CalculateChunksNeededForSize (bytes_available); 268d495c534SGreg Clayton if (num_chunks >= needed_chunks) 269d495c534SGreg Clayton { 270d495c534SGreg Clayton m_offset_to_chunk_size[last_offset] = needed_chunks; 271d495c534SGreg Clayton if (log) 272e7701feeSJim Ingham log->Printf ("[2] AllocatedBlock::ReserveBlock(%p) (size = %u (0x%x)) => offset = 0x%x, %u %u bit chunks - num_chunks %lu", this, size, size, last_offset, needed_chunks, m_chunk_size, m_offset_to_chunk_size.size()); 273d495c534SGreg Clayton addr = m_addr + last_offset; 274d495c534SGreg Clayton break; 275d495c534SGreg Clayton } 276d495c534SGreg Clayton } 277d495c534SGreg Clayton 278d495c534SGreg Clayton last_offset = pos->first + pos->second * m_chunk_size; 279d495c534SGreg Clayton 280d495c534SGreg Clayton if (++pos == end) 281d495c534SGreg Clayton { 282d495c534SGreg Clayton // Last entry... 283d495c534SGreg Clayton const uint32_t chunks_left = CalculateChunksNeededForSize (m_byte_size - last_offset); 284d495c534SGreg Clayton if (chunks_left >= needed_chunks) 285d495c534SGreg Clayton { 286d495c534SGreg Clayton m_offset_to_chunk_size[last_offset] = needed_chunks; 287d495c534SGreg Clayton if (log) 288e7701feeSJim Ingham log->Printf ("[3] AllocatedBlock::ReserveBlock(%p) (size = %u (0x%x)) => offset = 0x%x, %u %u bit chunks - num_chunks %lu", this, size, size, last_offset, needed_chunks, m_chunk_size, m_offset_to_chunk_size.size()); 289d495c534SGreg Clayton addr = m_addr + last_offset; 290d495c534SGreg Clayton break; 291d495c534SGreg Clayton } 292d495c534SGreg Clayton } 293d495c534SGreg Clayton } 294d495c534SGreg Clayton } 295d495c534SGreg Clayton // const uint32_t total_chunks = m_allocated.size (); 296d495c534SGreg Clayton // uint32_t unallocated_idx = 0; 297d495c534SGreg Clayton // uint32_t allocated_idx = m_allocated.find_first(); 298d495c534SGreg Clayton // uint32_t first_chunk_idx = UINT32_MAX; 299d495c534SGreg Clayton // uint32_t num_chunks; 300d495c534SGreg Clayton // while (1) 301d495c534SGreg Clayton // { 302d495c534SGreg Clayton // if (allocated_idx == UINT32_MAX) 303d495c534SGreg Clayton // { 304d495c534SGreg Clayton // // No more bits are set starting from unallocated_idx, so we 305d495c534SGreg Clayton // // either have enough chunks for the request, or we don't. 306d495c534SGreg Clayton // // Eiter way we break out of the while loop... 307d495c534SGreg Clayton // num_chunks = total_chunks - unallocated_idx; 308d495c534SGreg Clayton // if (needed_chunks <= num_chunks) 309d495c534SGreg Clayton // first_chunk_idx = unallocated_idx; 310d495c534SGreg Clayton // break; 311d495c534SGreg Clayton // } 312d495c534SGreg Clayton // else if (allocated_idx > unallocated_idx) 313d495c534SGreg Clayton // { 314d495c534SGreg Clayton // // We have some allocated chunks, check if there are enough 315d495c534SGreg Clayton // // free chunks to satisfy the request? 316d495c534SGreg Clayton // num_chunks = allocated_idx - unallocated_idx; 317d495c534SGreg Clayton // if (needed_chunks <= num_chunks) 318d495c534SGreg Clayton // { 319d495c534SGreg Clayton // // Yep, we have enough! 320d495c534SGreg Clayton // first_chunk_idx = unallocated_idx; 321d495c534SGreg Clayton // break; 322d495c534SGreg Clayton // } 323d495c534SGreg Clayton // } 324d495c534SGreg Clayton // 325d495c534SGreg Clayton // while (unallocated_idx < total_chunks) 326d495c534SGreg Clayton // { 327d495c534SGreg Clayton // if (m_allocated[unallocated_idx]) 328d495c534SGreg Clayton // ++unallocated_idx; 329d495c534SGreg Clayton // else 330d495c534SGreg Clayton // break; 331d495c534SGreg Clayton // } 332d495c534SGreg Clayton // 333d495c534SGreg Clayton // if (unallocated_idx >= total_chunks) 334d495c534SGreg Clayton // break; 335d495c534SGreg Clayton // 336d495c534SGreg Clayton // allocated_idx = m_allocated.find_next(unallocated_idx); 337d495c534SGreg Clayton // } 338d495c534SGreg Clayton // 339d495c534SGreg Clayton // if (first_chunk_idx != UINT32_MAX) 340d495c534SGreg Clayton // { 341d495c534SGreg Clayton // const uint32_t end_bit_idx = unallocated_idx + needed_chunks; 342d495c534SGreg Clayton // for (uint32_t idx = first_chunk_idx; idx < end_bit_idx; ++idx) 343d495c534SGreg Clayton // m_allocated.set(idx); 344d495c534SGreg Clayton // return m_addr + m_chunk_size * first_chunk_idx; 345d495c534SGreg Clayton // } 346d495c534SGreg Clayton } 347e7701feeSJim Ingham 348d495c534SGreg Clayton if (log) 349e7701feeSJim Ingham log->Printf ("AllocatedBlock::ReserveBlock(%p) (size = %u (0x%x)) => 0x%16.16" PRIx64, this, size, size, (uint64_t)addr); 350d495c534SGreg Clayton return addr; 351d495c534SGreg Clayton } 352d495c534SGreg Clayton 353d495c534SGreg Clayton bool 354d495c534SGreg Clayton AllocatedBlock::FreeBlock (addr_t addr) 355d495c534SGreg Clayton { 356d495c534SGreg Clayton uint32_t offset = addr - m_addr; 357d495c534SGreg Clayton OffsetToChunkSize::iterator pos = m_offset_to_chunk_size.find (offset); 358d495c534SGreg Clayton bool success = false; 359d495c534SGreg Clayton if (pos != m_offset_to_chunk_size.end()) 360d495c534SGreg Clayton { 361d495c534SGreg Clayton m_offset_to_chunk_size.erase (pos); 362d495c534SGreg Clayton success = true; 363d495c534SGreg Clayton } 3645160ce5cSGreg Clayton Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); 365d495c534SGreg Clayton if (log) 366e7701feeSJim Ingham log->Printf ("AllocatedBlock::FreeBlock(%p) (addr = 0x%16.16" PRIx64 ") => %i, num_chunks: %lu", this, (uint64_t)addr, success, m_offset_to_chunk_size.size()); 367d495c534SGreg Clayton return success; 368d495c534SGreg Clayton } 369d495c534SGreg Clayton 370d495c534SGreg Clayton 371d495c534SGreg Clayton AllocatedMemoryCache::AllocatedMemoryCache (Process &process) : 372d495c534SGreg Clayton m_process (process), 373d495c534SGreg Clayton m_mutex (Mutex::eMutexTypeRecursive), 374d495c534SGreg Clayton m_memory_map() 375d495c534SGreg Clayton { 376d495c534SGreg Clayton } 377d495c534SGreg Clayton 378d495c534SGreg Clayton AllocatedMemoryCache::~AllocatedMemoryCache () 379d495c534SGreg Clayton { 380d495c534SGreg Clayton } 381d495c534SGreg Clayton 382d495c534SGreg Clayton 383d495c534SGreg Clayton void 384d495c534SGreg Clayton AllocatedMemoryCache::Clear() 385d495c534SGreg Clayton { 386d495c534SGreg Clayton Mutex::Locker locker (m_mutex); 387d495c534SGreg Clayton if (m_process.IsAlive()) 388d495c534SGreg Clayton { 389d495c534SGreg Clayton PermissionsToBlockMap::iterator pos, end = m_memory_map.end(); 390d495c534SGreg Clayton for (pos = m_memory_map.begin(); pos != end; ++pos) 391d495c534SGreg Clayton m_process.DoDeallocateMemory(pos->second->GetBaseAddress()); 392d495c534SGreg Clayton } 393d495c534SGreg Clayton m_memory_map.clear(); 394d495c534SGreg Clayton } 395d495c534SGreg Clayton 396d495c534SGreg Clayton 397d495c534SGreg Clayton AllocatedMemoryCache::AllocatedBlockSP 398d495c534SGreg Clayton AllocatedMemoryCache::AllocatePage (uint32_t byte_size, 399d495c534SGreg Clayton uint32_t permissions, 400d495c534SGreg Clayton uint32_t chunk_size, 401d495c534SGreg Clayton Error &error) 402d495c534SGreg Clayton { 403d495c534SGreg Clayton AllocatedBlockSP block_sp; 404d495c534SGreg Clayton const size_t page_size = 4096; 405d495c534SGreg Clayton const size_t num_pages = (byte_size + page_size - 1) / page_size; 406d495c534SGreg Clayton const size_t page_byte_size = num_pages * page_size; 407d495c534SGreg Clayton 408d495c534SGreg Clayton addr_t addr = m_process.DoAllocateMemory(page_byte_size, permissions, error); 409d495c534SGreg Clayton 4105160ce5cSGreg Clayton Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 411d495c534SGreg Clayton if (log) 412d495c534SGreg Clayton { 413ffeba256SVirgile Bello log->Printf ("Process::DoAllocateMemory (byte_size = 0x%8.8" PRIx32 ", permissions = %s) => 0x%16.16" PRIx64, 414ffeba256SVirgile Bello (uint32_t)page_byte_size, 415d495c534SGreg Clayton GetPermissionsAsCString(permissions), 416d495c534SGreg Clayton (uint64_t)addr); 417d495c534SGreg Clayton } 418d495c534SGreg Clayton 419d495c534SGreg Clayton if (addr != LLDB_INVALID_ADDRESS) 420d495c534SGreg Clayton { 421d495c534SGreg Clayton block_sp.reset (new AllocatedBlock (addr, page_byte_size, permissions, chunk_size)); 422d495c534SGreg Clayton m_memory_map.insert (std::make_pair (permissions, block_sp)); 423d495c534SGreg Clayton } 424d495c534SGreg Clayton return block_sp; 425d495c534SGreg Clayton } 426d495c534SGreg Clayton 427d495c534SGreg Clayton lldb::addr_t 428d495c534SGreg Clayton AllocatedMemoryCache::AllocateMemory (size_t byte_size, 429d495c534SGreg Clayton uint32_t permissions, 430d495c534SGreg Clayton Error &error) 431d495c534SGreg Clayton { 432d495c534SGreg Clayton Mutex::Locker locker (m_mutex); 433d495c534SGreg Clayton 434d495c534SGreg Clayton addr_t addr = LLDB_INVALID_ADDRESS; 435d495c534SGreg Clayton std::pair<PermissionsToBlockMap::iterator, PermissionsToBlockMap::iterator> range = m_memory_map.equal_range (permissions); 436d495c534SGreg Clayton 437d495c534SGreg Clayton for (PermissionsToBlockMap::iterator pos = range.first; pos != range.second; ++pos) 438d495c534SGreg Clayton { 439d495c534SGreg Clayton addr = (*pos).second->ReserveBlock (byte_size); 440e7701feeSJim Ingham if (addr != LLDB_INVALID_ADDRESS) 441e7701feeSJim Ingham break; 442d495c534SGreg Clayton } 443d495c534SGreg Clayton 444d495c534SGreg Clayton if (addr == LLDB_INVALID_ADDRESS) 445d495c534SGreg Clayton { 446d495c534SGreg Clayton AllocatedBlockSP block_sp (AllocatePage (byte_size, permissions, 16, error)); 447d495c534SGreg Clayton 448d495c534SGreg Clayton if (block_sp) 449d495c534SGreg Clayton addr = block_sp->ReserveBlock (byte_size); 450d495c534SGreg Clayton } 4515160ce5cSGreg Clayton Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 452d495c534SGreg Clayton if (log) 453ffeba256SVirgile Bello log->Printf ("AllocatedMemoryCache::AllocateMemory (byte_size = 0x%8.8" PRIx32 ", permissions = %s) => 0x%16.16" PRIx64, (uint32_t)byte_size, GetPermissionsAsCString(permissions), (uint64_t)addr); 454d495c534SGreg Clayton return addr; 455d495c534SGreg Clayton } 456d495c534SGreg Clayton 457d495c534SGreg Clayton bool 458d495c534SGreg Clayton AllocatedMemoryCache::DeallocateMemory (lldb::addr_t addr) 459d495c534SGreg Clayton { 460d495c534SGreg Clayton Mutex::Locker locker (m_mutex); 461d495c534SGreg Clayton 462d495c534SGreg Clayton PermissionsToBlockMap::iterator pos, end = m_memory_map.end(); 463d495c534SGreg Clayton bool success = false; 464d495c534SGreg Clayton for (pos = m_memory_map.begin(); pos != end; ++pos) 465d495c534SGreg Clayton { 466d495c534SGreg Clayton if (pos->second->Contains (addr)) 467d495c534SGreg Clayton { 468d495c534SGreg Clayton success = pos->second->FreeBlock (addr); 469d495c534SGreg Clayton break; 470d495c534SGreg Clayton } 471d495c534SGreg Clayton } 4725160ce5cSGreg Clayton Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 473d495c534SGreg Clayton if (log) 474d01b2953SDaniel Malea log->Printf("AllocatedMemoryCache::DeallocateMemory (addr = 0x%16.16" PRIx64 ") => %i", (uint64_t)addr, success); 475d495c534SGreg Clayton return success; 476d495c534SGreg Clayton } 477d495c534SGreg Clayton 478d495c534SGreg Clayton 479