mirror of
				https://git.tardis.systems/mirrors/yuzu
				synced 2025-10-31 18:54:14 +01:00 
			
		
		
		
	common: Add free region manager
* Abstraction for placeholder region tracking in host_memory
This commit is contained in:
		
							parent
							
								
									20011dfeb8
								
							
						
					
					
						commit
						29e7d79a86
					
				| @ -52,6 +52,7 @@ add_library(common STATIC | ||||
|     fiber.cpp | ||||
|     fiber.h | ||||
|     fixed_point.h | ||||
|     free_region_manager.h | ||||
|     fs/file.cpp | ||||
|     fs/file.h | ||||
|     fs/fs.cpp | ||||
|  | ||||
							
								
								
									
										55
									
								
								src/common/free_region_manager.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/common/free_region_manager.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,55 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <mutex> | ||||
| #include <boost/icl/interval_set.hpp> | ||||
| 
 | ||||
| namespace Common { | ||||
| 
 | ||||
| class FreeRegionManager { | ||||
| public: | ||||
|     explicit FreeRegionManager() = default; | ||||
|     ~FreeRegionManager() = default; | ||||
| 
 | ||||
|     void SetAddressSpace(void* start, size_t size) { | ||||
|         this->FreeBlock(start, size); | ||||
|     } | ||||
| 
 | ||||
|     std::pair<void*, size_t> FreeBlock(void* block_ptr, size_t size) { | ||||
|         std::scoped_lock lk(m_mutex); | ||||
| 
 | ||||
|         // Check to see if we are adjacent to any regions.
 | ||||
|         auto start_address = reinterpret_cast<uintptr_t>(block_ptr); | ||||
|         auto end_address = start_address + size; | ||||
|         auto it = m_free_regions.find({start_address - 1, end_address + 1}); | ||||
| 
 | ||||
|         // If we are, join with them, ensuring we stay in bounds.
 | ||||
|         if (it != m_free_regions.end()) { | ||||
|             start_address = std::min(start_address, it->lower()); | ||||
|             end_address = std::max(end_address, it->upper()); | ||||
|         } | ||||
| 
 | ||||
|         // Free the relevant region.
 | ||||
|         m_free_regions.insert({start_address, end_address}); | ||||
| 
 | ||||
|         // Return the adjusted pointers.
 | ||||
|         block_ptr = reinterpret_cast<void*>(start_address); | ||||
|         size = end_address - start_address; | ||||
|         return {block_ptr, size}; | ||||
|     } | ||||
| 
 | ||||
|     void AllocateBlock(void* block_ptr, size_t size) { | ||||
|         std::scoped_lock lk(m_mutex); | ||||
| 
 | ||||
|         auto address = reinterpret_cast<uintptr_t>(block_ptr); | ||||
|         m_free_regions.subtract({address, address + size}); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     std::mutex m_mutex; | ||||
|     boost::icl::interval_set<uintptr_t> m_free_regions; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Common
 | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user