mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30: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
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <queue> | ||||
| 
 | ||||
| #include "common/common.h" | ||||
| 
 | ||||
| #include "core/hle/kernel/kernel.h" | ||||
|  | @ -12,69 +10,50 @@ | |||
| 
 | ||||
| namespace Kernel { | ||||
| 
 | ||||
| class Semaphore : public WaitObject { | ||||
| public: | ||||
|     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) { | ||||
| ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count, | ||||
|         std::string name) { | ||||
| 
 | ||||
|     if (initial_count > max_count) | ||||
|         return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel, | ||||
|                           ErrorSummary::WrongArgument, ErrorLevel::Permanent); | ||||
| 
 | ||||
|     Semaphore* semaphore = new Semaphore; | ||||
|     // TOOD(yuriks): Fix error reporting
 | ||||
|     *handle = g_handle_table.Create(semaphore).ValueOr(INVALID_HANDLE); | ||||
|     SharedPtr<Semaphore> semaphore(new Semaphore); | ||||
|     // TOOD(yuriks): Don't create Handle (see Thread::Create())
 | ||||
|     CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(semaphore)); | ||||
| 
 | ||||
|     // When the semaphore is created, some slots are reserved for other threads,
 | ||||
|     // and the rest is reserved for the caller thread
 | ||||
|     semaphore->max_count = max_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) { | ||||
|     Semaphore* semaphore = g_handle_table.Get<Semaphore>(handle).get(); | ||||
|     if (semaphore == nullptr) | ||||
|         return InvalidHandle(ErrorModule::Kernel); | ||||
| bool Semaphore::ShouldWait() { | ||||
|     return available_count <= 0; | ||||
| } | ||||
| 
 | ||||
|     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,  | ||||
|                           ErrorSummary::InvalidArgument, ErrorLevel::Permanent); | ||||
| 
 | ||||
|     *count = semaphore->available_count; | ||||
|     semaphore->available_count += release_count; | ||||
|     s32 previous_count = available_count; | ||||
|     available_count += release_count; | ||||
| 
 | ||||
|     // 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
 | ||||
|     while (!semaphore->ShouldWait() && semaphore->WakeupNextThread() != nullptr) { | ||||
|         semaphore->Acquire(); | ||||
|     while (!ShouldWait() && WakeupNextThread() != nullptr) { | ||||
|         Acquire(); | ||||
|     } | ||||
| 
 | ||||
|     return RESULT_SUCCESS; | ||||
|     return MakeResult<s32>(previous_count); | ||||
| } | ||||
| 
 | ||||
| } // namespace
 | ||||
|  |  | |||
|  | @ -4,29 +4,50 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <queue> | ||||
| #include <string> | ||||
| 
 | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| #include "core/hle/kernel/kernel.h" | ||||
| 
 | ||||
| namespace Kernel { | ||||
| 
 | ||||
| /**
 | ||||
| class Semaphore : public WaitObject { | ||||
| public: | ||||
|     /**
 | ||||
|      * Creates a semaphore. | ||||
|      * @param handle Pointer to the handle of the newly created object | ||||
|      * @param initial_count Number of slots reserved for other threads | ||||
|      * @param max_count Maximum number of slots the semaphore can have | ||||
|      * @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. | ||||
|  * @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 | ||||
|  * @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
 | ||||
|  |  | |||
|  | @ -374,17 +374,38 @@ static Result GetThreadId(u32* thread_id, Handle handle) { | |||
| 
 | ||||
| /// Creates a semaphore
 | ||||
| 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", | ||||
|         initial_count, max_count, *semaphore); | ||||
|     return res.raw; | ||||
|     return RESULT_SUCCESS.raw; | ||||
| } | ||||
| 
 | ||||
| /// Releases a certain number of slots in a semaphore
 | ||||
| static Result ReleaseSemaphore(s32* count, Handle semaphore, s32 release_count) { | ||||
|     LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, semaphore); | ||||
|     ResultCode res = Kernel::ReleaseSemaphore(count, semaphore, release_count); | ||||
|     return res.raw; | ||||
| static Result ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { | ||||
|     using Kernel::Semaphore; | ||||
| 
 | ||||
|     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
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue