committed by
FernandoS27
23 changed files with 212 additions and 80 deletions
-
2src/core/CMakeLists.txt
-
5src/core/hle/kernel/client_session.cpp
-
2src/core/hle/kernel/client_session.h
-
13src/core/hle/kernel/kernel.cpp
-
7src/core/hle/kernel/kernel.h
-
2src/core/hle/kernel/process.cpp
-
4src/core/hle/kernel/process.h
-
14src/core/hle/kernel/readable_event.cpp
-
6src/core/hle/kernel/readable_event.h
-
4src/core/hle/kernel/server_port.cpp
-
2src/core/hle/kernel/server_port.h
-
10src/core/hle/kernel/server_session.cpp
-
2src/core/hle/kernel/server_session.h
-
5src/core/hle/kernel/session.cpp
-
2src/core/hle/kernel/session.h
-
67src/core/hle/kernel/svc.cpp
-
86src/core/hle/kernel/synchronization.cpp
-
34src/core/hle/kernel/synchronization.h
-
5src/core/hle/kernel/synchronization_object.cpp
-
10src/core/hle/kernel/synchronization_object.h
-
6src/core/hle/kernel/thread.cpp
-
1src/core/hle/kernel/thread.h
-
3src/core/hle/kernel/writable_event.cpp
@ -0,0 +1,86 @@ |
|||||
|
// Copyright 2020 yuzu Emulator Project
|
||||
|
// Licensed under GPLv2 or any later version
|
||||
|
// Refer to the license.txt file included.
|
||||
|
|
||||
|
#include "core/core.h"
|
||||
|
#include "core/hle/kernel/errors.h"
|
||||
|
#include "core/hle/kernel/kernel.h"
|
||||
|
#include "core/hle/kernel/scheduler.h"
|
||||
|
#include "core/hle/kernel/synchronization.h"
|
||||
|
#include "core/hle/kernel/synchronization_object.h"
|
||||
|
#include "core/hle/kernel/thread.h"
|
||||
|
|
||||
|
namespace Kernel { |
||||
|
|
||||
|
/// Default thread wakeup callback for WaitSynchronization
|
||||
|
static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread, |
||||
|
std::shared_ptr<SynchronizationObject> object, |
||||
|
std::size_t index) { |
||||
|
ASSERT(thread->GetStatus() == ThreadStatus::WaitSynch); |
||||
|
|
||||
|
if (reason == ThreadWakeupReason::Timeout) { |
||||
|
thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
ASSERT(reason == ThreadWakeupReason::Signal); |
||||
|
thread->SetWaitSynchronizationResult(RESULT_SUCCESS); |
||||
|
thread->SetWaitSynchronizationOutput(static_cast<u32>(index)); |
||||
|
return true; |
||||
|
}; |
||||
|
|
||||
|
Synchronization::Synchronization(Core::System& system) : system{system} {} |
||||
|
|
||||
|
void Synchronization::SignalObject(SynchronizationObject& obj) const { |
||||
|
if (obj.IsSignaled()) { |
||||
|
obj.WakeupAllWaitingThreads(); |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
std::pair<ResultCode, Handle> Synchronization::WaitFor( |
||||
|
std::vector<std::shared_ptr<SynchronizationObject>>& sync_objects, s64 nano_seconds) { |
||||
|
auto* const thread = system.CurrentScheduler().GetCurrentThread(); |
||||
|
// Find the first object that is acquirable in the provided list of objects
|
||||
|
auto itr = std::find_if(sync_objects.begin(), sync_objects.end(), |
||||
|
[thread](const std::shared_ptr<SynchronizationObject>& object) { |
||||
|
return object->IsSignaled(); |
||||
|
}); |
||||
|
|
||||
|
if (itr != sync_objects.end()) { |
||||
|
// We found a ready object, acquire it and set the result value
|
||||
|
SynchronizationObject* object = itr->get(); |
||||
|
object->Acquire(thread); |
||||
|
u32 index = static_cast<s32>(std::distance(sync_objects.begin(), itr)); |
||||
|
return {RESULT_SUCCESS, index}; |
||||
|
} |
||||
|
|
||||
|
// No objects were ready to be acquired, prepare to suspend the thread.
|
||||
|
|
||||
|
// If a timeout value of 0 was provided, just return the Timeout error code instead of
|
||||
|
// suspending the thread.
|
||||
|
if (nano_seconds == 0) { |
||||
|
return {RESULT_TIMEOUT, 0}; |
||||
|
} |
||||
|
|
||||
|
if (thread->IsSyncCancelled()) { |
||||
|
thread->SetSyncCancelled(false); |
||||
|
return {ERR_SYNCHRONIZATION_CANCELED, 0}; |
||||
|
} |
||||
|
|
||||
|
for (auto& object : sync_objects) { |
||||
|
object->AddWaitingThread(SharedFrom(thread)); |
||||
|
} |
||||
|
|
||||
|
thread->SetSynchronizationObjects(std::move(sync_objects)); |
||||
|
thread->SetStatus(ThreadStatus::WaitSynch); |
||||
|
|
||||
|
// Create an event to wake the thread up after the specified nanosecond delay has passed
|
||||
|
thread->WakeAfterDelay(nano_seconds); |
||||
|
thread->SetWakeupCallback(DefaultThreadWakeupCallback); |
||||
|
|
||||
|
system.PrepareReschedule(thread->GetProcessorID()); |
||||
|
|
||||
|
return {RESULT_TIMEOUT, 0}; |
||||
|
} |
||||
|
|
||||
|
} // namespace Kernel
|
||||
@ -0,0 +1,34 @@ |
|||||
|
// Copyright 2020 yuzu Emulator Project |
||||
|
// Licensed under GPLv2 or any later version |
||||
|
// Refer to the license.txt file included. |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <memory> |
||||
|
#include <utility> |
||||
|
|
||||
|
#include "core/hle/kernel/object.h" |
||||
|
#include "core/hle/result.h" |
||||
|
|
||||
|
namespace Core { |
||||
|
class System; |
||||
|
} // namespace Core |
||||
|
|
||||
|
namespace Kernel { |
||||
|
|
||||
|
class KernelCore; |
||||
|
class SynchronizationObject; |
||||
|
|
||||
|
class Synchronization { |
||||
|
public: |
||||
|
Synchronization(Core::System& system); |
||||
|
|
||||
|
void SignalObject(SynchronizationObject& obj) const; |
||||
|
|
||||
|
std::pair<ResultCode, Handle> WaitFor( |
||||
|
std::vector<std::shared_ptr<SynchronizationObject>>& sync_objects, s64 nano_seconds); |
||||
|
|
||||
|
private: |
||||
|
Core::System& system; |
||||
|
}; |
||||
|
} // namespace Kernel |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue