| 
									
										
										
										
											2015-05-12 15:25:15 -05:00
										 |  |  | // Copyright 2015 Citra Emulator Project
 | 
					
						
							|  |  |  | // Licensed under GPLv2 or any later version
 | 
					
						
							|  |  |  | // Refer to the license.txt file included.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-19 12:54:06 -05:00
										 |  |  | #include "core/hle/kernel/errors.h"
 | 
					
						
							| 
									
										
										
										
											2016-09-20 23:52:38 -07:00
										 |  |  | #include "core/hle/kernel/resource_limit.h"
 | 
					
						
							| 
									
										
										
										
											2018-11-19 12:54:06 -05:00
										 |  |  | #include "core/hle/result.h"
 | 
					
						
							| 
									
										
										
										
											2015-05-12 15:25:15 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace Kernel { | 
					
						
							| 
									
										
										
										
											2018-11-19 12:54:06 -05:00
										 |  |  | namespace { | 
					
						
							|  |  |  | constexpr std::size_t ResourceTypeToIndex(ResourceType type) { | 
					
						
							|  |  |  |     return static_cast<std::size_t>(type); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | } // Anonymous namespace
 | 
					
						
							| 
									
										
										
										
											2015-05-12 15:25:15 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-28 12:30:33 -04:00
										 |  |  | ResourceLimit::ResourceLimit(KernelCore& kernel) : Object{kernel} {} | 
					
						
							|  |  |  | ResourceLimit::~ResourceLimit() = default; | 
					
						
							| 
									
										
										
										
											2015-05-12 15:25:15 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-23 15:30:22 -04:00
										 |  |  | bool ResourceLimit::Reserve(ResourceType resource, s64 amount) { | 
					
						
							|  |  |  |     return Reserve(resource, amount, 10000000000); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResourceLimit::Reserve(ResourceType resource, s64 amount, u64 timeout) { | 
					
						
							|  |  |  |     const std::size_t index{ResourceTypeToIndex(resource)}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s64 new_value = current[index] + amount; | 
					
						
							| 
									
										
										
										
											2020-05-29 13:48:01 +10:00
										 |  |  |     if (new_value > limit[index] && available[index] + amount <= limit[index]) { | 
					
						
							| 
									
										
										
										
											2020-03-23 15:30:22 -04:00
										 |  |  |         // TODO(bunnei): This is wrong for multicore, we should wait the calling thread for timeout
 | 
					
						
							|  |  |  |         new_value = current[index] + amount; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (new_value <= limit[index]) { | 
					
						
							|  |  |  |         current[index] = new_value; | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ResourceLimit::Release(ResourceType resource, u64 amount) { | 
					
						
							|  |  |  |     Release(resource, amount, amount); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ResourceLimit::Release(ResourceType resource, u64 used_amount, u64 available_amount) { | 
					
						
							|  |  |  |     const std::size_t index{ResourceTypeToIndex(resource)}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     current[index] -= used_amount; | 
					
						
							|  |  |  |     available[index] -= available_amount; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-24 20:15:51 -05:00
										 |  |  | std::shared_ptr<ResourceLimit> ResourceLimit::Create(KernelCore& kernel) { | 
					
						
							|  |  |  |     return std::make_shared<ResourceLimit>(kernel); | 
					
						
							| 
									
										
										
										
											2015-05-12 15:25:15 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-19 12:54:06 -05:00
										 |  |  | s64 ResourceLimit::GetCurrentResourceValue(ResourceType resource) const { | 
					
						
							| 
									
										
										
										
											2020-03-23 15:30:22 -04:00
										 |  |  |     return limit.at(ResourceTypeToIndex(resource)) - current.at(ResourceTypeToIndex(resource)); | 
					
						
							| 
									
										
										
										
											2018-11-19 12:54:06 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | s64 ResourceLimit::GetMaxResourceValue(ResourceType resource) const { | 
					
						
							| 
									
										
										
										
											2020-03-23 15:30:22 -04:00
										 |  |  |     return limit.at(ResourceTypeToIndex(resource)); | 
					
						
							| 
									
										
										
										
											2015-05-12 15:25:15 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-19 12:54:06 -05:00
										 |  |  | ResultCode ResourceLimit::SetLimitValue(ResourceType resource, s64 value) { | 
					
						
							| 
									
										
										
										
											2020-03-23 15:30:22 -04:00
										 |  |  |     const std::size_t index{ResourceTypeToIndex(resource)}; | 
					
						
							|  |  |  |     if (current[index] <= value) { | 
					
						
							|  |  |  |         limit[index] = value; | 
					
						
							|  |  |  |         return RESULT_SUCCESS; | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2020-04-29 14:53:53 +10:00
										 |  |  |         LOG_ERROR(Kernel, "Limit value is too large! resource={}, value={}, index={}", | 
					
						
							|  |  |  |                   static_cast<u32>(resource), value, index); | 
					
						
							| 
									
										
										
										
											2018-11-19 12:54:06 -05:00
										 |  |  |         return ERR_INVALID_STATE; | 
					
						
							| 
									
										
										
										
											2015-05-12 15:25:15 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-01-20 00:48:02 -07:00
										 |  |  | } // namespace Kernel
 |