mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Kernel: Convert Semaphore to not use Handles
This commit is contained in:
		
							parent
							
								
									4bb33dfc30
								
							
						
					
					
						commit
						d9b19be1d9
					
				
					 3 changed files with 87 additions and 66 deletions
				
			
		|  | @ -2,8 +2,6 @@ | ||||||
| // Licensed under GPLv2 or any later version
 | // Licensed under GPLv2 or any later version
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
| #include <queue> |  | ||||||
| 
 |  | ||||||
| #include "common/common.h" | #include "common/common.h" | ||||||
| 
 | 
 | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
|  | @ -12,69 +10,50 @@ | ||||||
| 
 | 
 | ||||||
| namespace Kernel { | namespace Kernel { | ||||||
| 
 | 
 | ||||||
| class Semaphore : public WaitObject { | ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count, | ||||||
| public: |         std::string name) { | ||||||
|     std::string GetTypeName() const override { return "Semaphore"; } |  | ||||||
|     std::string GetName() const override { return name; } |  | ||||||
| 
 |  | ||||||
|     static const HandleType HANDLE_TYPE = HandleType::Semaphore; |  | ||||||
|     HandleType GetHandleType() const override { return HANDLE_TYPE; } |  | ||||||
| 
 |  | ||||||
|     s32 max_count;                              ///< Maximum number of simultaneous holders the semaphore can have
 |  | ||||||
|     s32 available_count;                        ///< Number of free slots left in the semaphore
 |  | ||||||
|     std::string name;                           ///< Name of semaphore (optional)
 |  | ||||||
| 
 |  | ||||||
|     bool ShouldWait() override { |  | ||||||
|         return available_count <= 0; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     void Acquire() override { |  | ||||||
|         _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); |  | ||||||
|         --available_count; |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 |  | ||||||
| 
 |  | ||||||
| ResultCode CreateSemaphore(Handle* handle, s32 initial_count,  |  | ||||||
|     s32 max_count, const std::string& name) { |  | ||||||
| 
 | 
 | ||||||
|     if (initial_count > max_count) |     if (initial_count > max_count) | ||||||
|         return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel, |         return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel, | ||||||
|                           ErrorSummary::WrongArgument, ErrorLevel::Permanent); |                           ErrorSummary::WrongArgument, ErrorLevel::Permanent); | ||||||
| 
 | 
 | ||||||
|     Semaphore* semaphore = new Semaphore; |     SharedPtr<Semaphore> semaphore(new Semaphore); | ||||||
|     // TOOD(yuriks): Fix error reporting
 |     // TOOD(yuriks): Don't create Handle (see Thread::Create())
 | ||||||
|     *handle = g_handle_table.Create(semaphore).ValueOr(INVALID_HANDLE); |     CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(semaphore)); | ||||||
| 
 | 
 | ||||||
|     // When the semaphore is created, some slots are reserved for other threads,
 |     // When the semaphore is created, some slots are reserved for other threads,
 | ||||||
|     // and the rest is reserved for the caller thread
 |     // and the rest is reserved for the caller thread
 | ||||||
|     semaphore->max_count = max_count; |     semaphore->max_count = max_count; | ||||||
|     semaphore->available_count = initial_count; |     semaphore->available_count = initial_count; | ||||||
|     semaphore->name = name; |     semaphore->name = std::move(name); | ||||||
| 
 | 
 | ||||||
|     return RESULT_SUCCESS; |     return MakeResult<SharedPtr<Semaphore>>(std::move(semaphore)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { | bool Semaphore::ShouldWait() { | ||||||
|     Semaphore* semaphore = g_handle_table.Get<Semaphore>(handle).get(); |     return available_count <= 0; | ||||||
|     if (semaphore == nullptr) | } | ||||||
|         return InvalidHandle(ErrorModule::Kernel); |  | ||||||
| 
 | 
 | ||||||
|     if (semaphore->max_count - semaphore->available_count < release_count) | void Semaphore::Acquire() { | ||||||
|  |     _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); | ||||||
|  |     --available_count; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ResultVal<s32> Semaphore::Release(s32 release_count) { | ||||||
|  |     if (max_count - available_count < release_count) | ||||||
|         return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel,  |         return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel,  | ||||||
|                           ErrorSummary::InvalidArgument, ErrorLevel::Permanent); |                           ErrorSummary::InvalidArgument, ErrorLevel::Permanent); | ||||||
| 
 | 
 | ||||||
|     *count = semaphore->available_count; |     s32 previous_count = available_count; | ||||||
|     semaphore->available_count += release_count; |     available_count += release_count; | ||||||
| 
 | 
 | ||||||
|     // Notify some of the threads that the semaphore has been released
 |     // Notify some of the threads that the semaphore has been released
 | ||||||
|     // stop once the semaphore is full again or there are no more waiting threads
 |     // stop once the semaphore is full again or there are no more waiting threads
 | ||||||
|     while (!semaphore->ShouldWait() && semaphore->WakeupNextThread() != nullptr) { |     while (!ShouldWait() && WakeupNextThread() != nullptr) { | ||||||
|         semaphore->Acquire(); |         Acquire(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return RESULT_SUCCESS; |     return MakeResult<s32>(previous_count); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace
 | } // namespace
 | ||||||
|  |  | ||||||
|  | @ -4,29 +4,50 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include <queue> | ||||||
|  | #include <string> | ||||||
|  | 
 | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| 
 | 
 | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
| 
 | 
 | ||||||
| namespace Kernel { | namespace Kernel { | ||||||
| 
 | 
 | ||||||
|  | class Semaphore : public WaitObject { | ||||||
|  | public: | ||||||
|     /**
 |     /**
 | ||||||
|      * Creates a semaphore. |      * Creates a semaphore. | ||||||
|      * @param handle Pointer to the handle of the newly created object |      * @param handle Pointer to the handle of the newly created object | ||||||
|      * @param initial_count Number of slots reserved for other threads |      * @param initial_count Number of slots reserved for other threads | ||||||
|      * @param max_count Maximum number of slots the semaphore can have |      * @param max_count Maximum number of slots the semaphore can have | ||||||
|      * @param name Optional name of semaphore |      * @param name Optional name of semaphore | ||||||
|  * @return ResultCode of the error |      * @return The created semaphore | ||||||
|      */ |      */ | ||||||
| ResultCode CreateSemaphore(Handle* handle, s32 initial_count, s32 max_count, const std::string& name = "Unknown"); |     static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count, | ||||||
|  |             std::string name = "Unknown"); | ||||||
|  | 
 | ||||||
|  |     std::string GetTypeName() const override { return "Semaphore"; } | ||||||
|  |     std::string GetName() const override { return name; } | ||||||
|  | 
 | ||||||
|  |     static const HandleType HANDLE_TYPE = HandleType::Semaphore; | ||||||
|  |     HandleType GetHandleType() const override { return HANDLE_TYPE; } | ||||||
|  | 
 | ||||||
|  |     s32 max_count;                              ///< Maximum number of simultaneous holders the semaphore can have
 | ||||||
|  |     s32 available_count;                        ///< Number of free slots left in the semaphore
 | ||||||
|  |     std::string name;                           ///< Name of semaphore (optional)
 | ||||||
|  | 
 | ||||||
|  |     bool ShouldWait() override; | ||||||
|  |     void Acquire() override; | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Releases a certain number of slots from a semaphore. |      * Releases a certain number of slots from a semaphore. | ||||||
|  * @param count The number of free slots the semaphore had before this call |  | ||||||
|  * @param handle The handle of the semaphore to release |  | ||||||
|      * @param release_count The number of slots to release |      * @param release_count The number of slots to release | ||||||
|  * @return ResultCode of the error |      * @return The number of free slots the semaphore had before this call | ||||||
|      */ |      */ | ||||||
| ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count); |     ResultVal<s32> Release(s32 release_count); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     Semaphore() = default; | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| } // namespace
 | } // namespace
 | ||||||
|  |  | ||||||
|  | @ -374,17 +374,38 @@ static Result GetThreadId(u32* thread_id, Handle handle) { | ||||||
| 
 | 
 | ||||||
| /// Creates a semaphore
 | /// Creates a semaphore
 | ||||||
| static Result CreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count) { | static Result CreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count) { | ||||||
|     ResultCode res = Kernel::CreateSemaphore(semaphore, initial_count, max_count); |     using Kernel::Semaphore; | ||||||
|  | 
 | ||||||
|  |     ResultVal<SharedPtr<Semaphore>> semaphore_res = Semaphore::Create(initial_count, max_count); | ||||||
|  |     if (semaphore_res.Failed()) | ||||||
|  |         return semaphore_res.Code().raw; | ||||||
|  | 
 | ||||||
|  |     ResultVal<Handle> handle_res = Kernel::g_handle_table.Create(*semaphore_res); | ||||||
|  |     if (handle_res.Failed()) | ||||||
|  |         return handle_res.Code().raw; | ||||||
|  | 
 | ||||||
|  |     *semaphore = *handle_res; | ||||||
|     LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X", |     LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X", | ||||||
|         initial_count, max_count, *semaphore); |         initial_count, max_count, *semaphore); | ||||||
|     return res.raw; |     return RESULT_SUCCESS.raw; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Releases a certain number of slots in a semaphore
 | /// Releases a certain number of slots in a semaphore
 | ||||||
| static Result ReleaseSemaphore(s32* count, Handle semaphore, s32 release_count) { | static Result ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { | ||||||
|     LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, semaphore); |     using Kernel::Semaphore; | ||||||
|     ResultCode res = Kernel::ReleaseSemaphore(count, semaphore, release_count); | 
 | ||||||
|     return res.raw; |     LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, handle); | ||||||
|  | 
 | ||||||
|  |     SharedPtr<Semaphore> semaphore = Kernel::g_handle_table.Get<Semaphore>(handle); | ||||||
|  |     if (semaphore == nullptr) | ||||||
|  |         return InvalidHandle(ErrorModule::Kernel).raw; | ||||||
|  | 
 | ||||||
|  |     ResultVal<s32> release_res = semaphore->Release(release_count); | ||||||
|  |     if (release_res.Failed()) | ||||||
|  |         return release_res.Code().raw; | ||||||
|  | 
 | ||||||
|  |     *count = *release_res; | ||||||
|  |     return RESULT_SUCCESS.raw; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Query memory
 | /// Query memory
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue