Merge pull request #5231 from hamish-milne/fix-address-arbiter-serialization
Fix Address Arbiter serialization
This commit is contained in:
commit
8a69172570
2 changed files with 64 additions and 11 deletions
|
@ -16,8 +16,6 @@
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Kernel namespace
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Kernel::AddressArbiter)
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
void AddressArbiter::WaitThread(std::shared_ptr<Thread> thread, VAddr wait_address) {
|
||||
|
@ -69,7 +67,8 @@ std::shared_ptr<Thread> AddressArbiter::ResumeHighestPriorityThread(VAddr addres
|
|||
return thread;
|
||||
}
|
||||
|
||||
AddressArbiter::AddressArbiter(KernelSystem& kernel) : Object(kernel), kernel(kernel) {}
|
||||
AddressArbiter::AddressArbiter(KernelSystem& kernel)
|
||||
: Object(kernel), kernel(kernel), timeout_callback(std::make_shared<Callback>(*this)) {}
|
||||
AddressArbiter::~AddressArbiter() {}
|
||||
|
||||
std::shared_ptr<AddressArbiter> KernelSystem::CreateAddressArbiter(std::string name) {
|
||||
|
@ -80,6 +79,24 @@ std::shared_ptr<AddressArbiter> KernelSystem::CreateAddressArbiter(std::string n
|
|||
return address_arbiter;
|
||||
}
|
||||
|
||||
class AddressArbiter::Callback : public WakeupCallback {
|
||||
public:
|
||||
explicit Callback(AddressArbiter& _parent) : parent(_parent) {}
|
||||
AddressArbiter& parent;
|
||||
|
||||
void WakeUp(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||
std::shared_ptr<WaitObject> object) override {
|
||||
parent.WakeUp(reason, std::move(thread), std::move(object));
|
||||
}
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& boost::serialization::base_object<WakeupCallback>(*this);
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
void AddressArbiter::WakeUp(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||
std::shared_ptr<WaitObject> object) {
|
||||
ASSERT(reason == ThreadWakeupReason::Timeout);
|
||||
|
@ -90,9 +107,6 @@ void AddressArbiter::WakeUp(ThreadWakeupReason reason, std::shared_ptr<Thread> t
|
|||
|
||||
ResultCode AddressArbiter::ArbitrateAddress(std::shared_ptr<Thread> thread, ArbitrationType type,
|
||||
VAddr address, s32 value, u64 nanoseconds) {
|
||||
|
||||
auto timeout_callback = std::dynamic_pointer_cast<WakeupCallback>(shared_from_this());
|
||||
|
||||
switch (type) {
|
||||
|
||||
// Signal thread(s) waiting for arbitrate address...
|
||||
|
@ -157,3 +171,23 @@ ResultCode AddressArbiter::ArbitrateAddress(std::shared_ptr<Thread> thread, Arbi
|
|||
}
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
namespace boost::serialization {
|
||||
|
||||
template <class Archive>
|
||||
void save_construct_data(Archive& ar, const Kernel::AddressArbiter::Callback* t,
|
||||
const unsigned int) {
|
||||
ar << Kernel::SharedFrom(&t->parent);
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void load_construct_data(Archive& ar, Kernel::AddressArbiter::Callback* t, const unsigned int) {
|
||||
std::shared_ptr<Kernel::AddressArbiter> parent;
|
||||
ar >> parent;
|
||||
::new (t) Kernel::AddressArbiter::Callback(*parent);
|
||||
}
|
||||
|
||||
} // namespace boost::serialization
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(Kernel::AddressArbiter)
|
||||
SERIALIZE_EXPORT_IMPL(Kernel::AddressArbiter::Callback)
|
||||
|
|
|
@ -59,8 +59,7 @@ public:
|
|||
ResultCode ArbitrateAddress(std::shared_ptr<Thread> thread, ArbitrationType type, VAddr address,
|
||||
s32 value, u64 nanoseconds);
|
||||
|
||||
void WakeUp(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||
std::shared_ptr<WaitObject> object);
|
||||
class Callback;
|
||||
|
||||
private:
|
||||
KernelSystem& kernel;
|
||||
|
@ -78,20 +77,40 @@ private:
|
|||
/// Threads waiting for the address arbiter to be signaled.
|
||||
std::vector<std::shared_ptr<Thread>> waiting_threads;
|
||||
|
||||
std::shared_ptr<Callback> timeout_callback;
|
||||
|
||||
void WakeUp(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||
std::shared_ptr<WaitObject> object);
|
||||
|
||||
class DummyCallback : public WakeupCallback {
|
||||
public:
|
||||
void WakeUp(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||
std::shared_ptr<WaitObject> object) override {}
|
||||
};
|
||||
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& boost::serialization::base_object<Object>(*this);
|
||||
if (file_version > 0) {
|
||||
ar& boost::serialization::base_object<WakeupCallback>(*this);
|
||||
if (file_version == 1) {
|
||||
// This rigmarole is needed because in past versions, AddressArbiter inherited
|
||||
// WakeupCallback But it turns out this breaks shared_from_this, so we split it out.
|
||||
// Using a dummy class to deserialize a base_object allows compatibility to be
|
||||
// maintained.
|
||||
DummyCallback x;
|
||||
ar& boost::serialization::base_object<WakeupCallback>(x);
|
||||
}
|
||||
ar& name;
|
||||
ar& waiting_threads;
|
||||
if (file_version > 1) {
|
||||
ar& timeout_callback;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Kernel::AddressArbiter)
|
||||
BOOST_CLASS_VERSION(Kernel::AddressArbiter, 1)
|
||||
BOOST_CLASS_EXPORT_KEY(Kernel::AddressArbiter::Callback)
|
||||
BOOST_CLASS_VERSION(Kernel::AddressArbiter, 2)
|
||||
CONSTRUCT_KERNEL_OBJECT(Kernel::AddressArbiter)
|
||||
|
|
Loading…
Reference in a new issue