citra-emu
/
citra-canary
Archived
1
0
Fork 0

Added CPU, mutex, process, thread, timer

This commit is contained in:
Hamish Milne 2019-08-12 17:01:33 +01:00 committed by zhupengfei
parent 06891d9454
commit f557d26b40
20 changed files with 299 additions and 41 deletions

2
externals/boost vendored

@ -1 +1 @@
Subproject commit 19ccdcc6fbd026f98ed83dea32ff0398120fbb32 Subproject commit f4850c2975a0d977b7479664b8d4a6f03300a042

View File

@ -91,6 +91,7 @@ add_library(common STATIC
scm_rev.h scm_rev.h
scope_exit.h scope_exit.h
serialization/atomic.h serialization/atomic.h
serialization/boost_flat_set.h
serialization/boost_vector.hpp serialization/boost_vector.hpp
string_util.cpp string_util.cpp
string_util.h string_util.h

View File

@ -0,0 +1,37 @@
#pragma once
#include "common/common_types.h"
#include <boost/container/flat_set.hpp>
#include <boost/serialization/split_free.hpp>
namespace boost::serialization {
template <class Archive, class T>
void save(Archive& ar, const boost::container::flat_set<T>& set, const unsigned int file_version)
{
ar << static_cast<u64>(set.size());
for (auto &v : set) {
ar << v;
}
}
template <class Archive, class T>
void load(Archive& ar, boost::container::flat_set<T>& set, const unsigned int file_version)
{
u64 count{};
ar >> count;
set.clear();
for (auto i = 0; i < count; i++) {
T value{};
ar >> value;
set.insert(value);
}
}
template <class Archive, class T>
void serialize(Archive& ar, boost::container::flat_set<T>& set, const unsigned int file_version)
{
boost::serialization::split_free(ar, set, file_version);
}
}

View File

@ -6,6 +6,9 @@
#include <array> #include <array>
#include <deque> #include <deque>
#include <boost/serialization/deque.hpp>
#include <boost/serialization/split_member.hpp>
#include "common/common_types.h"
namespace Common { namespace Common {
@ -156,6 +159,34 @@ private:
Queue* first; Queue* first;
// The priority level queues of thread ids. // The priority level queues of thread ids.
std::array<Queue, NUM_QUEUES> queues; std::array<Queue, NUM_QUEUES> queues;
friend class boost::serialization::access;
template <class Archive>
void save(Archive& ar, const unsigned int file_version) const
{
s32 idx = first == UnlinkedTag() ? -1 : static_cast<s32>(first - &queues[0]);
ar << idx;
for (auto i = 0; i < NUM_QUEUES; i++) {
s32 idx1 = first == UnlinkedTag() ? -1 : static_cast<s32>(queues[i].next_nonempty - &queues[0]);
ar << idx1;
ar << queues[i].data;
}
}
template <class Archive>
void load(Archive& ar, const unsigned int file_version)
{
s32 idx;
ar >> idx;
first = idx < 0 ? UnlinkedTag() : &queues[idx];
for (auto i = 0; i < NUM_QUEUES; i++) {
ar >> idx;
queues[i].next_nonempty = idx < 0 ? UnlinkedTag() : &queues[idx];
ar >> queues[i].data;
}
}
BOOST_SERIALIZATION_SPLIT_MEMBER()
}; };
} // namespace Common } // namespace Common

View File

@ -6,6 +6,7 @@
#include <cstddef> #include <cstddef>
#include <memory> #include <memory>
#include <boost/serialization/split_member.hpp>
#include "common/common_types.h" #include "common/common_types.h"
#include "core/arm/skyeye_common/arm_regformat.h" #include "core/arm/skyeye_common/arm_regformat.h"
#include "core/arm/skyeye_common/vfp/asm_vfp.h" #include "core/arm/skyeye_common/vfp/asm_vfp.h"
@ -16,6 +17,48 @@ public:
virtual ~ARM_Interface() {} virtual ~ARM_Interface() {}
class ThreadContext { class ThreadContext {
friend class boost::serialization::access;
template <class Archive>
void save(Archive& ar, const unsigned int file_version) const
{
for (auto i = 0; i < 16; i++) {
auto r = GetCpuRegister(i);
ar << r;
}
for (auto i = 0; i < 16; i++) {
auto r = GetFpuRegister(i);
ar << r;
}
auto r1 = GetCpsr();
ar << r1;
auto r2 = GetFpscr();
ar << r2;
auto r3 = GetFpexc();
ar << r3;
}
template <class Archive>
void load(Archive& ar, const unsigned int file_version)
{
u32 r;
for (auto i = 0; i < 16; i++) {
ar >> r;
SetCpuRegister(i, r);
}
for (auto i = 0; i < 16; i++) {
ar >> r;
SetFpuRegister(i, r);
}
ar >> r;
SetCpsr(r);
ar >> r;
SetFpscr(r);
ar >> r;
SetFpexc(r);
}
BOOST_SERIALIZATION_SPLIT_MEMBER()
public: public:
virtual ~ThreadContext() = default; virtual ~ThreadContext() = default;
@ -143,7 +186,7 @@ public:
* @param reg The CP15 register to retrieve the value from. * @param reg The CP15 register to retrieve the value from.
* @return the value stored in the given CP15 register. * @return the value stored in the given CP15 register.
*/ */
virtual u32 GetCP15Register(CP15Register reg) = 0; virtual u32 GetCP15Register(CP15Register reg) const = 0;
/** /**
* Stores the given value into the indicated CP15 register. * Stores the given value into the indicated CP15 register.
@ -172,4 +215,61 @@ public:
/// Prepare core for thread reschedule (if needed to correctly handle state) /// Prepare core for thread reschedule (if needed to correctly handle state)
virtual void PrepareReschedule() = 0; virtual void PrepareReschedule() = 0;
private:
friend class boost::serialization::access;
template <class Archive>
void save(Archive& ar, const unsigned int file_version) const
{
for (auto i = 0; i < 15; i++) {
auto r = GetReg(i);
ar << r;
}
auto pc = GetPC();
ar << pc;
auto cpsr = GetCPSR();
ar << cpsr;
for (auto i = 0; i < 32; i++) {
auto r = GetVFPReg(i);
ar << r;
}
for (auto i = 0; i < VFPSystemRegister::VFP_SYSTEM_REGISTER_COUNT; i++) {
auto r = GetVFPSystemReg(static_cast<VFPSystemRegister>(i));
ar << r;
}
for (auto i = 0; i < CP15Register::CP15_REGISTER_COUNT; i++) {
auto r = GetCP15Register(static_cast<CP15Register>(i));
ar << r;
}
}
template <class Archive>
void load(Archive& ar, const unsigned int file_version)
{
u32 r;
for (auto i = 0; i < 15; i++) {
ar >> r;
SetReg(i, r);
}
ar >> r;
SetPC(r);
ar >> r;
SetCPSR(r);
for (auto i = 0; i < 32; i++) {
ar >> r;
SetVFPReg(i, r);
}
for (auto i = 0; i < VFPSystemRegister::VFP_SYSTEM_REGISTER_COUNT; i++) {
ar >> r;
SetVFPSystemReg(static_cast<VFPSystemRegister>(i), r);
}
for (auto i = 0; i < CP15Register::CP15_REGISTER_COUNT; i++) {
ar >> r;
SetCP15Register(static_cast<CP15Register>(i), r);
}
// TODO: Clear caches etc?
}
BOOST_SERIALIZATION_SPLIT_MEMBER()
}; };

View File

@ -235,7 +235,7 @@ void ARM_Dynarmic::SetCPSR(u32 cpsr) {
jit->SetCpsr(cpsr); jit->SetCpsr(cpsr);
} }
u32 ARM_Dynarmic::GetCP15Register(CP15Register reg) { u32 ARM_Dynarmic::GetCP15Register(CP15Register reg) const {
return interpreter_state->CP15[reg]; return interpreter_state->CP15[reg];
} }

View File

@ -40,7 +40,7 @@ public:
void SetVFPSystemReg(VFPSystemRegister reg, u32 value) override; void SetVFPSystemReg(VFPSystemRegister reg, u32 value) override;
u32 GetCPSR() const override; u32 GetCPSR() const override;
void SetCPSR(u32 cpsr) override; void SetCPSR(u32 cpsr) override;
u32 GetCP15Register(CP15Register reg) override; u32 GetCP15Register(CP15Register reg) const override;
void SetCP15Register(CP15Register reg, u32 value) override; void SetCP15Register(CP15Register reg, u32 value) override;
std::unique_ptr<ThreadContext> NewContext() const override; std::unique_ptr<ThreadContext> NewContext() const override;

View File

@ -138,7 +138,7 @@ void ARM_DynCom::SetCPSR(u32 cpsr) {
state->Cpsr = cpsr; state->Cpsr = cpsr;
} }
u32 ARM_DynCom::GetCP15Register(CP15Register reg) { u32 ARM_DynCom::GetCP15Register(CP15Register reg) const {
return state->CP15[reg]; return state->CP15[reg];
} }

View File

@ -41,7 +41,7 @@ public:
void SetVFPSystemReg(VFPSystemRegister reg, u32 value) override; void SetVFPSystemReg(VFPSystemRegister reg, u32 value) override;
u32 GetCPSR() const override; u32 GetCPSR() const override;
void SetCPSR(u32 cpsr) override; void SetCPSR(u32 cpsr) override;
u32 GetCP15Register(CP15Register reg) override; u32 GetCP15Register(CP15Register reg) const override;
void SetCP15Register(CP15Register reg, u32 value) override; void SetCP15Register(CP15Register reg, u32 value) override;
std::unique_ptr<ThreadContext> NewContext() const override; std::unique_ptr<ThreadContext> NewContext() const override;

View File

@ -9,6 +9,7 @@
// bootrom. Because we're not emulating this, and essentially just "stubbing" the functionality, I'm // bootrom. Because we're not emulating this, and essentially just "stubbing" the functionality, I'm
// putting this as a subset of HLE for now. // putting this as a subset of HLE for now.
#include <boost/serialization/binary_object.hpp>
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/swap.h" #include "common/swap.h"
@ -56,6 +57,14 @@ public:
private: private:
ConfigMemDef config_mem; ConfigMemDef config_mem;
friend class boost::serialization::access;
template <class Archive>
void serialize(Archive& ar, const unsigned int file_version)
{
auto o_config_mem = boost::serialization::binary_object(&config_mem, sizeof(config_mem));
ar & o_config_mem;
}
}; };
} // namespace ConfigMem } // namespace ConfigMem

View File

@ -109,17 +109,17 @@ template <class Archive>
void KernelSystem::serialize(Archive& ar, const unsigned int file_version) void KernelSystem::serialize(Archive& ar, const unsigned int file_version)
{ {
ar & named_ports; ar & named_ports;
// TODO: CPU ar & *current_cpu.get();
// NB: subsystem references and prepare_reschedule_callback are constant // NB: subsystem references and prepare_reschedule_callback are constant
ar & *resource_limits.get(); ar & *resource_limits.get();
ar & next_object_id; ar & next_object_id;
//ar & *timer_manager.get(); ar & *timer_manager.get();
ar & next_process_id; ar & next_process_id;
ar & process_list; ar & process_list;
ar & current_process; ar & current_process;
// ar & *thread_manager.get(); ar & *thread_manager.get();
//ar & *config_mem_handler.get(); ar & *config_mem_handler.get();
//ar & *shared_page_handler.get(); ar & *shared_page_handler.get();
} }
SERIALIZE_IMPL(KernelSystem) SERIALIZE_IMPL(KernelSystem)

View File

@ -23,11 +23,12 @@ void ReleaseThreadMutexes(Thread* thread) {
thread->held_mutexes.clear(); thread->held_mutexes.clear();
} }
Mutex::Mutex(KernelSystem& kernel) : WaitObject(kernel), kernel(kernel) {} Mutex::Mutex() : kernel(*g_kernel) {}
Mutex::~Mutex() {} Mutex::~Mutex() {}
std::shared_ptr<Mutex> KernelSystem::CreateMutex(bool initial_locked, std::string name) { std::shared_ptr<Mutex> KernelSystem::CreateMutex(bool initial_locked, std::string name) {
auto mutex{std::make_shared<Mutex>(*this)}; auto mutex{std::make_shared<Mutex>()};
mutex->Init(*this);
mutex->lock_count = 0; mutex->lock_count = 0;
mutex->name = std::move(name); mutex->name = std::move(name);

View File

@ -17,7 +17,7 @@ class Thread;
class Mutex final : public WaitObject { class Mutex final : public WaitObject {
public: public:
explicit Mutex(KernelSystem& kernel); explicit Mutex();
~Mutex() override; ~Mutex() override;
std::string GetTypeName() const override { std::string GetTypeName() const override {
@ -68,7 +68,6 @@ private:
ar & priority; ar & priority;
ar & name; ar & name;
ar & holding_thread; ar & holding_thread;
ar & kernel; // TODO: Check that this works!
} }
}; };

View File

@ -4,9 +4,13 @@
#include <algorithm> #include <algorithm>
#include <memory> #include <memory>
#include <boost/serialization/array.hpp>
#include <boost/serialization/bitset.hpp>
#include "common/archives.h"
#include "common/assert.h" #include "common/assert.h"
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/serialization/boost_vector.hpp"
#include "core/hle/kernel/errors.h" #include "core/hle/kernel/errors.h"
#include "core/hle/kernel/memory.h" #include "core/hle/kernel/memory.h"
#include "core/hle/kernel/process.h" #include "core/hle/kernel/process.h"
@ -17,6 +21,28 @@
namespace Kernel { namespace Kernel {
template <class Archive>
void Process::serialize(Archive& ar, const unsigned int file_version)
{
ar & boost::serialization::base_object<Object>(*this);
ar & handle_table;
ar & codeset;
ar & resource_limit;
ar & svc_access_mask;
ar & handle_table_size;
ar & (boost::container::vector<AddressMapping, boost::container::dtl::static_storage_allocator<AddressMapping, 8> >&)address_mappings;
ar & flags.raw;
ar & kernel_version;
ar & ideal_processor;
ar & process_id;
ar & vm_manager;
ar & memory_used;
ar & memory_region;
ar & tls_slots;
}
SERIALIZE_IMPL(Process)
std::shared_ptr<CodeSet> KernelSystem::CreateCodeSet(std::string name, u64 program_id) { std::shared_ptr<CodeSet> KernelSystem::CreateCodeSet(std::string name, u64 program_id) {
auto codeset{std::make_shared<CodeSet>()}; auto codeset{std::make_shared<CodeSet>()};
codeset->Init(*this); codeset->Init(*this);

View File

@ -11,13 +11,10 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <boost/container/static_vector.hpp> #include <boost/container/static_vector.hpp>
#include <boost/serialization/array.hpp>
#include <boost/serialization/bitset.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/vector.hpp> #include <boost/serialization/vector.hpp>
#include <boost/serialization/base_object.hpp>
#include "common/bit_field.h" #include "common/bit_field.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/serialization/boost_vector.hpp"
#include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/object.h" #include "core/hle/kernel/object.h"
#include "core/hle/kernel/vm_manager.h" #include "core/hle/kernel/vm_manager.h"
@ -234,23 +231,6 @@ private:
friend class boost::serialization::access; friend class boost::serialization::access;
template <class Archive> template <class Archive>
void serialize(Archive& ar, const unsigned int file_version) void serialize(Archive& ar, const unsigned int file_version);
{
ar & boost::serialization::base_object<Object>(*this);
ar & handle_table;
ar & codeset;
ar & resource_limit;
ar & svc_access_mask;
ar & handle_table_size;
ar & (boost::container::vector<AddressMapping, boost::container::dtl::static_storage_allocator<AddressMapping, 8> >&)address_mappings;
ar & flags.raw;
ar & kernel_version;
ar & ideal_processor;
ar & process_id;
ar & vm_manager;
ar & memory_used;
ar & memory_region;
ar & tls_slots;
}
}; };
} // namespace Kernel } // namespace Kernel

View File

@ -13,6 +13,7 @@
#include <chrono> #include <chrono>
#include <ctime> #include <ctime>
#include <memory> #include <memory>
#include <boost/serialization/binary_object.hpp>
#include "common/bit_field.h" #include "common/bit_field.h"
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "common/common_types.h" #include "common/common_types.h"
@ -104,6 +105,14 @@ private:
std::chrono::seconds init_time; std::chrono::seconds init_time;
SharedPageDef shared_page; SharedPageDef shared_page;
friend class boost::serialization::access;
template <class Archive>
void serialize(Archive& ar, const unsigned int file_version)
{
auto o_shared_page = boost::serialization::binary_object(&shared_page, sizeof(shared_page));
ar & o_shared_page;
}
}; };
} // namespace SharedPage } // namespace SharedPage

View File

@ -6,10 +6,12 @@
#include <list> #include <list>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include "common/archives.h"
#include "common/assert.h" #include "common/assert.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/math_util.h" #include "common/math_util.h"
#include "common/serialization/boost_flat_set.h"
#include "core/arm/arm_interface.h" #include "core/arm/arm_interface.h"
#include "core/arm/skyeye_common/armstate.h" #include "core/arm/skyeye_common/armstate.h"
#include "core/core.h" #include "core/core.h"
@ -25,6 +27,30 @@
namespace Kernel { namespace Kernel {
template <class Archive>
void Thread::serialize(Archive& ar, const unsigned int file_version)
{
ar & *context.get();
ar & thread_id;
ar & status;
ar & entry_point;
ar & stack_top;
ar & nominal_priority;
ar & current_priority;
ar & last_running_ticks;
ar & processor_id;
ar & tls_address;
ar & held_mutexes;
ar & pending_mutexes;
ar & owner_process;
ar & wait_objects;
ar & wait_address;
ar & name;
// TODO: How the hell to do wakeup_callback
}
SERIALIZE_IMPL(Thread)
bool Thread::ShouldWait(const Thread* thread) const { bool Thread::ShouldWait(const Thread* thread) const {
return status != ThreadStatus::Dead; return status != ThreadStatus::Dead;
} }

View File

@ -9,6 +9,9 @@
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include <boost/container/flat_set.hpp> #include <boost/container/flat_set.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/unordered_map.hpp>
#include <boost/serialization/vector.hpp>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/thread_queue_list.h" #include "common/thread_queue_list.h"
#include "core/arm/arm_interface.h" #include "core/arm/arm_interface.h"
@ -145,6 +148,17 @@ private:
friend class Thread; friend class Thread;
friend class KernelSystem; friend class KernelSystem;
friend class boost::serialization::access;
template <class Archive>
void serialize(Archive& ar, const unsigned int file_version)
{
ar & next_thread_id;
ar & current_thread;
ar & ready_queue;
ar & wakeup_callback_table;
ar & thread_list;
}
}; };
class Thread final : public WaitObject { class Thread final : public WaitObject {
@ -305,6 +319,10 @@ public:
private: private:
ThreadManager& thread_manager; ThreadManager& thread_manager;
friend class boost::serialization::access;
template <class Archive>
void serialize(Archive& ar, const unsigned int file_version);
}; };
/** /**

View File

@ -14,15 +14,15 @@
namespace Kernel { namespace Kernel {
Timer::Timer(KernelSystem& kernel) Timer::Timer() : kernel(*g_kernel), timer_manager(g_kernel->GetTimerManager()) {}
: WaitObject(kernel), kernel(kernel), timer_manager(kernel.GetTimerManager()) {}
Timer::~Timer() { Timer::~Timer() {
Cancel(); Cancel();
timer_manager.timer_callback_table.erase(callback_id); timer_manager.timer_callback_table.erase(callback_id);
} }
std::shared_ptr<Timer> KernelSystem::CreateTimer(ResetType reset_type, std::string name) { std::shared_ptr<Timer> KernelSystem::CreateTimer(ResetType reset_type, std::string name) {
auto timer{std::make_shared<Timer>(*this)}; auto timer{std::make_shared<Timer>()};
timer->Init(*this);
timer->reset_type = reset_type; timer->reset_type = reset_type;
timer->signaled = false; timer->signaled = false;

View File

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <boost/serialization/unordered_map.hpp>
#include "common/common_types.h" #include "common/common_types.h"
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/hle/kernel/object.h" #include "core/hle/kernel/object.h"
@ -33,11 +34,19 @@ private:
friend class Timer; friend class Timer;
friend class KernelSystem; friend class KernelSystem;
friend class boost::serialization::access;
template <class Archive>
void serialize(Archive& ar, const unsigned int file_version)
{
ar & next_timer_callback_id;
ar & timer_callback_table;
}
}; };
class Timer final : public WaitObject { class Timer final : public WaitObject {
public: public:
explicit Timer(KernelSystem& kernel); explicit Timer();
~Timer() override; ~Timer() override;
std::string GetTypeName() const override { std::string GetTypeName() const override {
@ -103,6 +112,18 @@ private:
TimerManager& timer_manager; TimerManager& timer_manager;
friend class KernelSystem; friend class KernelSystem;
friend class boost::serialization::access;
template <class Archive>
void serialize(Archive& ar, const unsigned int file_version)
{
ar & reset_type;
ar & initial_delay;
ar & interval_delay;
ar & signaled;
ar & name;
ar & callback_id;
}
}; };
} // namespace Kernel } // namespace Kernel