mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +00:00 
			
		
		
		
	SVC: Implemented the Timer service calls.
This commit is contained in:
		
							parent
							
								
									3eca33c6a4
								
							
						
					
					
						commit
						07044651ef
					
				@ -31,6 +31,7 @@ set(SRCS
 | 
			
		||||
            hle/kernel/mutex.cpp
 | 
			
		||||
            hle/kernel/semaphore.cpp
 | 
			
		||||
            hle/kernel/shared_memory.cpp
 | 
			
		||||
            hle/kernel/timer.cpp
 | 
			
		||||
            hle/kernel/thread.cpp
 | 
			
		||||
            hle/service/ac_u.cpp
 | 
			
		||||
            hle/service/act_u.cpp
 | 
			
		||||
@ -123,6 +124,7 @@ set(HEADERS
 | 
			
		||||
            hle/kernel/semaphore.h
 | 
			
		||||
            hle/kernel/session.h
 | 
			
		||||
            hle/kernel/shared_memory.h
 | 
			
		||||
            hle/kernel/timer.h
 | 
			
		||||
            hle/kernel/thread.h
 | 
			
		||||
            hle/service/ac_u.h
 | 
			
		||||
            hle/service/act_u.h
 | 
			
		||||
 | 
			
		||||
@ -135,6 +135,12 @@ template<s32 func(u32*, u32, u32, u32, u32)> void Wrap() {
 | 
			
		||||
    FuncReturn(retval);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<s32 func(u32, s64, s64)> void Wrap() {
 | 
			
		||||
    s64 param1 = ((u64)PARAM(3) << 32) | PARAM(2);
 | 
			
		||||
    s64 param2 = ((u64)PARAM(4) << 32) | PARAM(1);
 | 
			
		||||
    FuncReturn(func(PARAM(0), param1, param2));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Function wrappers that return type u32
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -9,6 +9,7 @@
 | 
			
		||||
#include "core/core.h"
 | 
			
		||||
#include "core/hle/kernel/kernel.h"
 | 
			
		||||
#include "core/hle/kernel/thread.h"
 | 
			
		||||
#include "core/hle/kernel/timer.h"
 | 
			
		||||
 | 
			
		||||
namespace Kernel {
 | 
			
		||||
 | 
			
		||||
@ -105,12 +106,13 @@ void HandleTable::Clear() {
 | 
			
		||||
/// Initialize the kernel
 | 
			
		||||
void Init() {
 | 
			
		||||
    Kernel::ThreadingInit();
 | 
			
		||||
    Kernel::TimersInit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Shutdown the kernel
 | 
			
		||||
void Shutdown() {
 | 
			
		||||
    Kernel::ThreadingShutdown();
 | 
			
		||||
 | 
			
		||||
    Kernel::TimersShutdown();
 | 
			
		||||
    g_handle_table.Clear(); // Free all kernel objects
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -39,6 +39,7 @@ enum class HandleType : u32 {
 | 
			
		||||
    Process         = 8,
 | 
			
		||||
    AddressArbiter  = 9,
 | 
			
		||||
    Semaphore       = 10,
 | 
			
		||||
    Timer           = 11
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
 | 
			
		||||
@ -43,6 +43,7 @@ enum WaitType {
 | 
			
		||||
    WAITTYPE_MUTEX,
 | 
			
		||||
    WAITTYPE_SYNCH,
 | 
			
		||||
    WAITTYPE_ARB,
 | 
			
		||||
    WAITTYPE_TIMER,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
namespace Kernel {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										142
									
								
								src/core/hle/kernel/timer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								src/core/hle/kernel/timer.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,142 @@
 | 
			
		||||
// Copyright 2015 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include <set>
 | 
			
		||||
 | 
			
		||||
#include "common/common.h"
 | 
			
		||||
 | 
			
		||||
#include "core/core_timing.h"
 | 
			
		||||
#include "core/hle/kernel/kernel.h"
 | 
			
		||||
#include "core/hle/kernel/timer.h"
 | 
			
		||||
#include "core/hle/kernel/thread.h"
 | 
			
		||||
 | 
			
		||||
namespace Kernel {
 | 
			
		||||
 | 
			
		||||
class Timer : public Object {
 | 
			
		||||
public:
 | 
			
		||||
    std::string GetTypeName() const override { return "Timer"; }
 | 
			
		||||
    std::string GetName() const override { return name; }
 | 
			
		||||
 | 
			
		||||
    static const HandleType HANDLE_TYPE = HandleType::Timer;
 | 
			
		||||
    HandleType GetHandleType() const override { return HANDLE_TYPE; }
 | 
			
		||||
 | 
			
		||||
    ResetType reset_type;                   ///< The ResetType of this timer
 | 
			
		||||
 | 
			
		||||
    bool signaled;                          ///< Whether the timer has been signaled or not
 | 
			
		||||
    std::set<Handle> waiting_threads;       ///< Threads that are waiting for the timer
 | 
			
		||||
    std::string name;                       ///< Name of timer (optional)
 | 
			
		||||
 | 
			
		||||
    u64 initial_delay;                      ///< The delay until the timer fires for the first time
 | 
			
		||||
    u64 interval_delay;                     ///< The delay until the timer fires after the first time
 | 
			
		||||
 | 
			
		||||
    ResultVal<bool> WaitSynchronization() override {
 | 
			
		||||
        bool wait = !signaled;
 | 
			
		||||
        if (wait) {
 | 
			
		||||
            waiting_threads.insert(GetCurrentThreadHandle());
 | 
			
		||||
            Kernel::WaitCurrentThread(WAITTYPE_TIMER, GetHandle());
 | 
			
		||||
        }
 | 
			
		||||
        return MakeResult<bool>(wait);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Creates a timer.
 | 
			
		||||
 * @param handle Reference to handle for the newly created timer
 | 
			
		||||
 * @param reset_type ResetType describing how to create timer
 | 
			
		||||
 * @param name Optional name of timer
 | 
			
		||||
 * @return Newly created Timer object
 | 
			
		||||
 */
 | 
			
		||||
Timer* CreateTimer(Handle& handle, const ResetType reset_type, const std::string& name) {
 | 
			
		||||
    Timer* timer = new Timer;
 | 
			
		||||
 | 
			
		||||
    handle = Kernel::g_handle_table.Create(timer).ValueOr(INVALID_HANDLE);
 | 
			
		||||
 | 
			
		||||
    timer->reset_type = reset_type;
 | 
			
		||||
    timer->signaled = false;
 | 
			
		||||
    timer->name = name;
 | 
			
		||||
    timer->initial_delay = 0;
 | 
			
		||||
    timer->interval_delay = 0;
 | 
			
		||||
    return timer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode CreateTimer(Handle* handle, const ResetType reset_type, const std::string& name) {
 | 
			
		||||
    CreateTimer(*handle, reset_type, name);
 | 
			
		||||
    return RESULT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode ClearTimer(Handle handle) {
 | 
			
		||||
    Timer* timer = Kernel::g_handle_table.Get<Timer>(handle);
 | 
			
		||||
    
 | 
			
		||||
    if (timer == nullptr)
 | 
			
		||||
        return InvalidHandle(ErrorModule::Kernel);
 | 
			
		||||
 | 
			
		||||
    timer->signaled = false;
 | 
			
		||||
    return RESULT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// The event type of the generic timer callback event
 | 
			
		||||
static int TimerCallbackEventType = -1;
 | 
			
		||||
 | 
			
		||||
/// The timer callback event, called when a timer is fired
 | 
			
		||||
static void TimerCallback(u64 timer_handle, int cycles_late) {
 | 
			
		||||
    Timer* timer = Kernel::g_handle_table.Get<Timer>(timer_handle);
 | 
			
		||||
 | 
			
		||||
    if (timer == nullptr) {
 | 
			
		||||
        LOG_CRITICAL(Kernel, "Callback fired for invalid timer %u", timer_handle);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    LOG_TRACE(Kernel, "Timer %u fired", timer_handle);
 | 
			
		||||
 | 
			
		||||
    timer->signaled = true;
 | 
			
		||||
 | 
			
		||||
    // Resume all waiting threads
 | 
			
		||||
    for (Handle thread : timer->waiting_threads)
 | 
			
		||||
        ResumeThreadFromWait(thread);
 | 
			
		||||
 | 
			
		||||
    timer->waiting_threads.clear();
 | 
			
		||||
 | 
			
		||||
    if (timer->reset_type == RESETTYPE_ONESHOT)
 | 
			
		||||
        timer->signaled = false;
 | 
			
		||||
 | 
			
		||||
    if (timer->interval_delay != 0) {
 | 
			
		||||
        // Reschedule the timer with the interval delay
 | 
			
		||||
        u64 interval_microseconds = timer->interval_delay / 1000;
 | 
			
		||||
        CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late, 
 | 
			
		||||
                TimerCallbackEventType, timer_handle);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode SetTimer(Handle handle, s64 initial, s64 interval) {
 | 
			
		||||
    Timer* timer = Kernel::g_handle_table.Get<Timer>(handle);
 | 
			
		||||
 | 
			
		||||
    if (timer == nullptr)
 | 
			
		||||
        return InvalidHandle(ErrorModule::Kernel);
 | 
			
		||||
 | 
			
		||||
    timer->initial_delay = initial;
 | 
			
		||||
    timer->interval_delay = interval;
 | 
			
		||||
 | 
			
		||||
    u64 initial_microseconds = initial / 1000;
 | 
			
		||||
    CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), TimerCallbackEventType, handle);
 | 
			
		||||
    return RESULT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode CancelTimer(Handle handle) {
 | 
			
		||||
    Timer* timer = Kernel::g_handle_table.Get<Timer>(handle);
 | 
			
		||||
 | 
			
		||||
    if (timer == nullptr)
 | 
			
		||||
        return InvalidHandle(ErrorModule::Kernel);
 | 
			
		||||
 | 
			
		||||
    CoreTiming::UnscheduleEvent(TimerCallbackEventType, handle);
 | 
			
		||||
    return RESULT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TimersInit() {
 | 
			
		||||
    TimerCallbackEventType = CoreTiming::RegisterEvent("TimerCallback", TimerCallback);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TimersShutdown() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace
 | 
			
		||||
							
								
								
									
										47
									
								
								src/core/hle/kernel/timer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/core/hle/kernel/timer.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
			
		||||
// Copyright 2015 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
 | 
			
		||||
#include "core/hle/kernel/kernel.h"
 | 
			
		||||
#include "core/hle/svc.h"
 | 
			
		||||
 | 
			
		||||
namespace Kernel {
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Cancels a timer
 | 
			
		||||
 * @param handle Handle of the timer to cancel
 | 
			
		||||
 */
 | 
			
		||||
ResultCode CancelTimer(Handle handle);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Starts a timer with the specified initial delay and interval
 | 
			
		||||
 * @param handle Handle of the timer to start
 | 
			
		||||
 * @param initial Delay until the timer is first fired
 | 
			
		||||
 * @param interval Delay until the timer is fired after the first time
 | 
			
		||||
 */
 | 
			
		||||
ResultCode SetTimer(Handle handle, s64 initial, s64 interval);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Clears a timer
 | 
			
		||||
 * @param handle Handle of the timer to clear
 | 
			
		||||
 */
 | 
			
		||||
ResultCode ClearTimer(Handle handle);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Creates a timer
 | 
			
		||||
 * @param Handle to newly created Timer object
 | 
			
		||||
 * @param reset_type ResetType describing how to create the timer
 | 
			
		||||
 * @param name Optional name of timer
 | 
			
		||||
 * @return ResultCode of the error
 | 
			
		||||
 */
 | 
			
		||||
ResultCode CreateTimer(Handle* handle, const ResetType reset_type, const std::string& name="Unknown");
 | 
			
		||||
 | 
			
		||||
/// Initializes the required variables for timers
 | 
			
		||||
void TimersInit();
 | 
			
		||||
/// Tears down the timer variables
 | 
			
		||||
void TimersShutdown();
 | 
			
		||||
} // namespace
 | 
			
		||||
@ -15,6 +15,7 @@
 | 
			
		||||
#include "core/hle/kernel/semaphore.h"
 | 
			
		||||
#include "core/hle/kernel/shared_memory.h"
 | 
			
		||||
#include "core/hle/kernel/thread.h"
 | 
			
		||||
#include "core/hle/kernel/timer.h"
 | 
			
		||||
 | 
			
		||||
#include "core/hle/function_wrappers.h"
 | 
			
		||||
#include "core/hle/result.h"
 | 
			
		||||
@ -139,6 +140,7 @@ static Result WaitSynchronization1(Handle handle, s64 nano_seconds) {
 | 
			
		||||
/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
 | 
			
		||||
static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all,
 | 
			
		||||
    s64 nano_seconds) {
 | 
			
		||||
 | 
			
		||||
    // TODO(bunnei): Do something with nano_seconds, currently ignoring this
 | 
			
		||||
    bool unlock_all = true;
 | 
			
		||||
    bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated
 | 
			
		||||
@ -338,6 +340,32 @@ static Result ClearEvent(Handle evt) {
 | 
			
		||||
    return Kernel::ClearEvent(evt).raw;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Creates a timer
 | 
			
		||||
static Result CreateTimer(Handle* handle, u32 reset_type) {
 | 
			
		||||
    ResultCode res = Kernel::CreateTimer(handle, static_cast<ResetType>(reset_type));
 | 
			
		||||
    LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X",
 | 
			
		||||
        reset_type, *handle);
 | 
			
		||||
    return res.raw;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Clears a timer
 | 
			
		||||
static Result ClearTimer(Handle handle) {
 | 
			
		||||
    LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle);
 | 
			
		||||
    return Kernel::ClearTimer(handle).raw;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Starts a timer
 | 
			
		||||
static Result SetTimer(Handle handle, s64 initial, s64 interval) {
 | 
			
		||||
    LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle);
 | 
			
		||||
    return Kernel::SetTimer(handle, initial, interval).raw;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Cancels a timer
 | 
			
		||||
static Result CancelTimer(Handle handle) {
 | 
			
		||||
    LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle);
 | 
			
		||||
    return Kernel::CancelTimer(handle).raw;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Sleep the current thread
 | 
			
		||||
static void SleepThread(s64 nanoseconds) {
 | 
			
		||||
    LOG_TRACE(Kernel_SVC, "called nanoseconds=%lld", nanoseconds);
 | 
			
		||||
@ -391,10 +419,10 @@ const HLE::FunctionDef SVC_Table[] = {
 | 
			
		||||
    {0x17, HLE::Wrap<CreateEvent>,          "CreateEvent"},
 | 
			
		||||
    {0x18, HLE::Wrap<SignalEvent>,          "SignalEvent"},
 | 
			
		||||
    {0x19, HLE::Wrap<ClearEvent>,           "ClearEvent"},
 | 
			
		||||
    {0x1A, nullptr,                         "CreateTimer"},
 | 
			
		||||
    {0x1B, nullptr,                         "SetTimer"},
 | 
			
		||||
    {0x1C, nullptr,                         "CancelTimer"},
 | 
			
		||||
    {0x1D, nullptr,                         "ClearTimer"},
 | 
			
		||||
    {0x1A, HLE::Wrap<CreateTimer>,          "CreateTimer"},
 | 
			
		||||
    {0x1B, HLE::Wrap<SetTimer>,             "SetTimer"},
 | 
			
		||||
    {0x1C, HLE::Wrap<CancelTimer>,          "CancelTimer"},
 | 
			
		||||
    {0x1D, HLE::Wrap<ClearTimer>,           "ClearTimer"},
 | 
			
		||||
    {0x1E, HLE::Wrap<CreateMemoryBlock>,    "CreateMemoryBlock"},
 | 
			
		||||
    {0x1F, HLE::Wrap<MapMemoryBlock>,       "MapMemoryBlock"},
 | 
			
		||||
    {0x20, nullptr,                         "UnmapMemoryBlock"},
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user