Use load_construct_data for kernel objects

This commit is contained in:
Hamish Milne 2019-12-27 18:52:33 +00:00 committed by zhupengfei
parent 3ed8d95866
commit 6917eaf53b
35 changed files with 158 additions and 113 deletions

5
TODO
View file

@ -3,7 +3,7 @@
✔ Memory @done(19-08-13 15:41)
☐ Page tables
☐ Skip N3DS RAM if unused
✔ DSP @done(19-08-13 15:41)
☐ DSP
✔ Service manager @started(19-12-23 00:36) @done(19-12-23 11:38) @lasted(11h2m3s)
✔ Fix or ignore inverse map @done(19-12-23 12:46)
☐ App loader
@ -16,6 +16,7 @@
☐ Telemetry session
☐ Replace SERIALIZE_AS_POD with BOOST_IS_BITWISE_SERIALIZABLE
☐ Review constructor/initialization code
☐ Fix CI
✔ HW @done(19-08-13 15:41)
✔ GPU regs @done(19-08-13 15:41)
✔ LCD regs @done(19-08-13 15:41)
@ -78,7 +79,7 @@
✔ DSP @done(19-12-26 18:10)
✔ ERR @done(19-12-26 18:14)
✔ FRD @done(19-12-26 19:09)
☐ FS
✔ FS @done(19-12-27 11:46)
☐ GSP
☐ HID
☐ HTTP

View file

@ -6,7 +6,6 @@
#include <memory>
#include <vector>
#include "boost/serialization/array.hpp"
#include "audio_core/audio_types.h"
#include "audio_core/time_stretch.h"
#include "common/common_types.h"

View file

@ -54,6 +54,7 @@ add_custom_command(OUTPUT scm_rev.cpp
add_library(common STATIC
alignment.h
announce_multiplayer_room.h
archives.h
assert.h
detached_tasks.cpp
detached_tasks.h
@ -66,6 +67,7 @@ add_library(common STATIC
common_funcs.h
common_paths.h
common_types.h
construct.h
file_util.cpp
file_util.h
hash.h
@ -91,8 +93,10 @@ add_library(common STATIC
scm_rev.h
scope_exit.h
serialization/atomic.h
serialization/boost_discrete_interval.hpp
serialization/boost_flat_set.h
serialization/boost_vector.hpp
serialization/optional.h
string_util.cpp
string_util.h
swap.h

View file

@ -14,14 +14,12 @@ public:
#define BOOST_SERIALIZATION_CONSTRUCT(T) \
namespace boost { namespace serialization { \
\
template<class Archive> \
inline void save_construct_data( \
Archive & ar, const T * t, const unsigned int file_version \
){ \
construct_access::save_construct(ar, t, file_version); \
} \
\
template<class Archive> \
inline void load_construct_data( \
Archive & ar, T * t, const unsigned int file_version \

View file

@ -3,8 +3,8 @@
#include <atomic>
#include <boost/serialization/split_free.hpp>
namespace boost::serialization
{
namespace boost::serialization {
template <class Archive, class T>
void serialize(Archive& ar, std::atomic<T>& value, const unsigned int file_version)
{

View file

@ -4,7 +4,7 @@
#include <memory>
#include <utility>
#include "boost/serialization/array.hpp"
#include <boost/serialization/array.hpp>
#include "audio_core/dsp_interface.h"
#include "audio_core/hle/hle.h"
#include "audio_core/lle/lle.h"

View file

@ -69,12 +69,11 @@ std::shared_ptr<Thread> AddressArbiter::ResumeHighestPriorityThread(VAddr addres
return thread;
}
AddressArbiter::AddressArbiter() : kernel(Core::Global<KernelSystem>()) {}
AddressArbiter::AddressArbiter(KernelSystem& kernel) : Object(kernel), kernel(kernel) {}
AddressArbiter::~AddressArbiter() {}
std::shared_ptr<AddressArbiter> KernelSystem::CreateAddressArbiter(std::string name) {
auto address_arbiter{std::make_shared<AddressArbiter>()};
address_arbiter->Init(*this);
auto address_arbiter{std::make_shared<AddressArbiter>(*this)};
address_arbiter->name = std::move(name);

View file

@ -36,7 +36,7 @@ enum class ArbitrationType : u32 {
class AddressArbiter final : public Object {
public:
explicit AddressArbiter();
explicit AddressArbiter(KernelSystem& kernel);
~AddressArbiter() override;
std::string GetTypeName() const override {
@ -85,3 +85,4 @@ private:
} // namespace Kernel
BOOST_CLASS_EXPORT_KEY(Kernel::AddressArbiter)
CONSTRUCT_KERNEL_OBJECT(Kernel::AddressArbiter)

View file

@ -17,6 +17,9 @@ SERIALIZE_EXPORT_IMPL(Kernel::ClientPort)
namespace Kernel {
ClientPort::ClientPort(KernelSystem& kernel) : Object(kernel), kernel(kernel) {}
ClientPort::~ClientPort() = default;
ResultVal<std::shared_ptr<ClientSession>> ClientPort::Connect() {
// Note: Threads do not wait for the server endpoint to call
// AcceptSession before returning from this call.
@ -27,7 +30,7 @@ ResultVal<std::shared_ptr<ClientSession>> ClientPort::Connect() {
active_sessions++;
// Create a new session pair, let the created sessions inherit the parent port's HLE handler.
auto [server, client] = Core::Global<KernelSystem>().CreateSessionPair(server_port->GetName(), SharedFrom(this));
auto [server, client] = kernel.CreateSessionPair(server_port->GetName(), SharedFrom(this));
if (server_port->hle_handler)
server_port->hle_handler->ClientConnected(server);

View file

@ -18,6 +18,8 @@ class ClientSession;
class ClientPort final : public Object {
public:
explicit ClientPort(KernelSystem& kernel);
~ClientPort() override;
friend class ServerPort;
std::string GetTypeName() const override {
@ -51,6 +53,7 @@ public:
void ConnectionClosed();
private:
KernelSystem& kernel;
std::shared_ptr<ServerPort> server_port; ///< ServerPort associated with this client port.
u32 max_sessions = 0; ///< Maximum number of simultaneous sessions the port can have
u32 active_sessions = 0; ///< Number of currently open sessions to this port
@ -75,3 +78,4 @@ private:
} // namespace Kernel
BOOST_CLASS_EXPORT_KEY(Kernel::ClientPort)
CONSTRUCT_KERNEL_OBJECT(Kernel::ClientPort)

View file

@ -15,7 +15,7 @@ SERIALIZE_EXPORT_IMPL(Kernel::ClientSession)
namespace Kernel {
ClientSession::ClientSession() = default;
ClientSession::ClientSession(KernelSystem& kernel) : Object(kernel) {}
ClientSession::~ClientSession() {
// This destructor will be called automatically when the last ClientSession handle is closed by
// the emulated application.

View file

@ -20,7 +20,7 @@ class Thread;
class ClientSession final : public Object {
public:
explicit ClientSession();
explicit ClientSession(KernelSystem& kernel);
~ClientSession() override;
friend class KernelSystem;
@ -64,3 +64,4 @@ private:
} // namespace Kernel
BOOST_CLASS_EXPORT_KEY(Kernel::ClientSession)
CONSTRUCT_KERNEL_OBJECT(Kernel::ClientSession)

View file

@ -15,11 +15,11 @@ SERIALIZE_EXPORT_IMPL(Kernel::Event)
namespace Kernel {
Event::Event() : WaitObject() {}
Event::Event(KernelSystem& kernel) : WaitObject(kernel) {}
Event::~Event() {}
std::shared_ptr<Event> KernelSystem::CreateEvent(ResetType reset_type, std::string name) {
auto evt{std::make_shared<Event>()};
auto evt{std::make_shared<Event>(*this)};
evt->signaled = false;
evt->reset_type = reset_type;

View file

@ -13,7 +13,7 @@ namespace Kernel {
class Event final : public WaitObject {
public:
explicit Event();
explicit Event(KernelSystem& kernel);
~Event() override;
std::string GetTypeName() const override {
@ -65,3 +65,4 @@ private:
} // namespace Kernel
BOOST_CLASS_EXPORT_KEY(Kernel::Event)
CONSTRUCT_KERNEL_OBJECT(Kernel::Event)

View file

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

View file

@ -18,7 +18,7 @@ class Thread;
class Mutex final : public WaitObject {
public:
explicit Mutex();
explicit Mutex(KernelSystem& kernel);
~Mutex() override;
std::string GetTypeName() const override {
@ -81,3 +81,4 @@ void ReleaseThreadMutexes(Thread* thread);
} // namespace Kernel
BOOST_CLASS_EXPORT_KEY(Kernel::Mutex)
CONSTRUCT_KERNEL_OBJECT(Kernel::Mutex)

View file

@ -8,17 +8,7 @@
namespace Kernel {
// TODO: Remove this
Object::Object(KernelSystem& kernel)
{
}
Object::Object() = default;
void Object::Init(KernelSystem& kernel)
{
object_id = kernel.GenerateObjectID();
}
Object::Object(KernelSystem& kernel) : object_id{kernel.GenerateObjectID()} {}
Object::~Object() = default;

View file

@ -8,9 +8,12 @@
#include <memory>
#include <string>
#include <boost/serialization/access.hpp>
#include <boost/serialization/assume_abstract.hpp>
#include <boost/serialization/export.hpp>
#include "common/serialization/atomic.h"
#include "common/common_types.h"
#include "core/hle/kernel/kernel.h"
#include "core/global.h"
namespace Kernel {
@ -43,11 +46,8 @@ enum {
class Object : NonCopyable, public std::enable_shared_from_this<Object> {
public:
explicit Object(KernelSystem& kernel);
Object();
virtual ~Object();
virtual void Init(KernelSystem& kernel);
/// Returns a unique identifier for the object. For debugging purposes only.
u32 GetObjectId() const {
return object_id.load(std::memory_order_relaxed);
@ -99,3 +99,14 @@ inline std::shared_ptr<T> DynamicObjectCast(std::shared_ptr<Object> object) {
}
} // namespace Kernel
BOOST_SERIALIZATION_ASSUME_ABSTRACT(Kernel::Object)
#define CONSTRUCT_KERNEL_OBJECT(T) \
namespace boost::serialization { \
template<class Archive> \
inline void load_construct_data( \
Archive & ar, T * t, const unsigned int file_version \
){ \
::new(t)T(Core::Global<Kernel::KernelSystem>()); \
}}

View file

@ -20,6 +20,9 @@
#include "core/memory.h"
#include "core/global.h"
SERIALIZE_EXPORT_IMPL(Kernel::Process)
SERIALIZE_EXPORT_IMPL(Kernel::CodeSet)
namespace Kernel {
template <class Archive>
@ -46,8 +49,7 @@ void Process::serialize(Archive& ar, const unsigned int file_version)
SERIALIZE_IMPL(Process)
std::shared_ptr<CodeSet> KernelSystem::CreateCodeSet(std::string name, u64 program_id) {
auto codeset{std::make_shared<CodeSet>()};
codeset->Init(*this);
auto codeset{std::make_shared<CodeSet>(*this)};
codeset->name = std::move(name);
codeset->program_id = program_id;
@ -55,9 +57,11 @@ std::shared_ptr<CodeSet> KernelSystem::CreateCodeSet(std::string name, u64 progr
return codeset;
}
CodeSet::CodeSet(KernelSystem& kernel) : Object(kernel) {}
CodeSet::~CodeSet() {}
std::shared_ptr<Process> KernelSystem::CreateProcess(std::shared_ptr<CodeSet> code_set) {
auto process{std::make_shared<Process>()};
process->Init(*this);
auto process{std::make_shared<Process>(*this)};
process->codeset = std::move(code_set);
process->flags.raw = 0;
@ -428,12 +432,8 @@ ResultCode Process::Unmap(VAddr target, VAddr source, u32 size, VMAPermission pe
return RESULT_SUCCESS;
}
Kernel::Process::Process() : Kernel::Process::Process(Core::Global<KernelSystem>())
{
}
Kernel::Process::Process(KernelSystem& kernel) : kernel(kernel), handle_table(kernel), vm_manager(kernel.memory)
{
Kernel::Process::Process(KernelSystem& kernel)
: Object(kernel), handle_table(kernel), vm_manager(kernel.memory), kernel(kernel) {
kernel.memory.RegisterPageTable(&vm_manager.page_table);
}
Kernel::Process::~Process() {

View file

@ -65,6 +65,9 @@ struct MemoryRegionInfo;
class CodeSet final : public Object {
public:
explicit CodeSet(KernelSystem& kernel);
~CodeSet() override;
struct Segment {
std::size_t offset = 0;
VAddr addr = 0;
@ -143,8 +146,7 @@ private:
class Process final : public Object {
public:
Process();
explicit Process(KernelSystem& kernel);
explicit Process(Kernel::KernelSystem& kernel);
~Process() override;
std::string GetTypeName() const override {
@ -235,3 +237,8 @@ private:
void serialize(Archive& ar, const unsigned int file_version);
};
} // namespace Kernel
BOOST_CLASS_EXPORT_KEY(Kernel::CodeSet)
BOOST_CLASS_EXPORT_KEY(Kernel::Process)
CONSTRUCT_KERNEL_OBJECT(Kernel::CodeSet)
CONSTRUCT_KERNEL_OBJECT(Kernel::Process)

View file

@ -3,15 +3,20 @@
// Refer to the license.txt file included.
#include <cstring>
#include "common/archives.h"
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/hle/kernel/resource_limit.h"
SERIALIZE_EXPORT_IMPL(Kernel::ResourceLimit)
namespace Kernel {
ResourceLimit::ResourceLimit(KernelSystem& kernel) : Object(kernel) {}
ResourceLimit::~ResourceLimit() {}
std::shared_ptr<ResourceLimit> ResourceLimit::Create(KernelSystem& kernel, std::string name) {
auto resource_limit{std::make_shared<ResourceLimit>()};
resource_limit->Init(kernel);
auto resource_limit{std::make_shared<ResourceLimit>(kernel)};
resource_limit->name = std::move(name);
return resource_limit;

View file

@ -35,6 +35,8 @@ enum ResourceTypes {
class ResourceLimit final : public Object {
public:
explicit ResourceLimit(KernelSystem& kernel);
~ResourceLimit() override;
/**
* Creates a resource limit object.
@ -165,3 +167,6 @@ private:
};
} // namespace Kernel
BOOST_CLASS_EXPORT_KEY(Kernel::ResourceLimit)
CONSTRUCT_KERNEL_OBJECT(Kernel::ResourceLimit)

View file

@ -13,7 +13,7 @@ SERIALIZE_EXPORT_IMPL(Kernel::Semaphore)
namespace Kernel {
Semaphore::Semaphore() : WaitObject() {}
Semaphore::Semaphore(KernelSystem& kernel) : WaitObject(kernel) {}
Semaphore::~Semaphore() {}
ResultVal<std::shared_ptr<Semaphore>> KernelSystem::CreateSemaphore(s32 initial_count,
@ -23,7 +23,7 @@ ResultVal<std::shared_ptr<Semaphore>> KernelSystem::CreateSemaphore(s32 initial_
if (initial_count > max_count)
return ERR_INVALID_COMBINATION_KERNEL;
auto semaphore{std::make_shared<Semaphore>()};
auto semaphore{std::make_shared<Semaphore>(*this)};
// When the semaphore is created, some slots are reserved for other threads,
// and the rest is reserved for the caller thread

View file

@ -16,7 +16,7 @@ namespace Kernel {
class Semaphore final : public WaitObject {
public:
explicit Semaphore();
explicit Semaphore(KernelSystem& kernel);
~Semaphore() override;
std::string GetTypeName() const override {
@ -60,3 +60,4 @@ private:
} // namespace Kernel
BOOST_CLASS_EXPORT_KEY(Kernel::Semaphore)
CONSTRUCT_KERNEL_OBJECT(Kernel::Semaphore)

View file

@ -17,6 +17,9 @@ SERIALIZE_EXPORT_IMPL(Kernel::ServerPort)
namespace Kernel {
ServerPort::ServerPort(KernelSystem& kernel) : WaitObject(kernel) {}
ServerPort::~ServerPort() {}
ResultVal<std::shared_ptr<ServerSession>> ServerPort::Accept() {
if (pending_sessions.empty()) {
return ERR_NO_PENDING_SESSIONS;
@ -37,10 +40,8 @@ void ServerPort::Acquire(Thread* thread) {
}
KernelSystem::PortPair KernelSystem::CreatePortPair(u32 max_sessions, std::string name) {
auto server_port{std::make_shared<ServerPort>()};
server_port->Init(*this);
auto client_port{std::make_shared<ClientPort>()};
client_port->Init(*this);
auto server_port{std::make_shared<ServerPort>(*this)};
auto client_port{std::make_shared<ClientPort>(*this)};
server_port->name = name + "_Server";
client_port->name = name + "_Client";

View file

@ -25,6 +25,8 @@ class SessionRequestHandler;
class ServerPort final : public WaitObject {
public:
explicit ServerPort(KernelSystem& kernel);
~ServerPort() override;
std::string GetTypeName() const override {
return "ServerPort";
@ -73,3 +75,4 @@ private:
} // namespace Kernel
BOOST_CLASS_EXPORT_KEY(Kernel::ServerPort)
CONSTRUCT_KERNEL_OBJECT(Kernel::ServerPort)

View file

@ -16,7 +16,7 @@ SERIALIZE_EXPORT_IMPL(Kernel::ServerSession)
namespace Kernel {
ServerSession::ServerSession() : kernel(Core::Global<KernelSystem>()) {}
ServerSession::ServerSession(KernelSystem& kernel) : WaitObject(kernel), kernel(kernel) {}
ServerSession::~ServerSession() {
// This destructor will be called automatically when the last ServerSession handle is closed by
// the emulated application.
@ -33,8 +33,7 @@ ServerSession::~ServerSession() {
ResultVal<std::shared_ptr<ServerSession>> ServerSession::Create(KernelSystem& kernel,
std::string name) {
auto server_session{std::make_shared<ServerSession>()};
server_session->Init(kernel);
auto server_session{std::make_shared<ServerSession>(kernel)};
server_session->name = std::move(name);
server_session->parent = nullptr;
@ -127,8 +126,7 @@ ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread) {
KernelSystem::SessionPair KernelSystem::CreateSessionPair(const std::string& name,
std::shared_ptr<ClientPort> port) {
auto server_session = ServerSession::Create(*this, name + "_Server").Unwrap();
auto client_session{std::make_shared<ClientSession>()};
client_session->Init(*this);
auto client_session{std::make_shared<ClientSession>(*this)};
client_session->name = name + "_Client";
std::shared_ptr<Session> parent(new Session);

View file

@ -42,7 +42,7 @@ class Thread;
class ServerSession final : public WaitObject {
public:
~ServerSession() override;
explicit ServerSession();
explicit ServerSession(KernelSystem& kernel);
std::string GetName() const override {
return name;
@ -125,3 +125,4 @@ private:
} // namespace Kernel
BOOST_CLASS_EXPORT_KEY(Kernel::ServerSession)
CONSTRUCT_KERNEL_OBJECT(Kernel::ServerSession)

View file

@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include <cstring>
#include "common/archives.h"
#include "common/logging/log.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/memory.h"
@ -10,9 +11,11 @@
#include "core/memory.h"
#include "core/global.h"
SERIALIZE_EXPORT_IMPL(Kernel::SharedMemory)
namespace Kernel {
SharedMemory::SharedMemory() : Object(Core::Global<KernelSystem>()), kernel(Core::Global<KernelSystem>()) {}
SharedMemory::SharedMemory(KernelSystem& kernel) : Object(kernel), kernel(kernel) {}
SharedMemory::~SharedMemory() {
for (const auto& interval : holding_memory) {
kernel.GetMemoryRegion(MemoryRegion::SYSTEM)
@ -28,7 +31,7 @@ SharedMemory::~SharedMemory() {
ResultVal<std::shared_ptr<SharedMemory>> KernelSystem::CreateSharedMemory(
Process* owner_process, u32 size, MemoryPermission permissions,
MemoryPermission other_permissions, VAddr address, MemoryRegion region, std::string name) {
auto shared_memory{std::make_shared<SharedMemory>()};
auto shared_memory{std::make_shared<SharedMemory>(*this)};
shared_memory->owner_process = owner_process;
shared_memory->name = std::move(name);
@ -73,7 +76,7 @@ ResultVal<std::shared_ptr<SharedMemory>> KernelSystem::CreateSharedMemory(
std::shared_ptr<SharedMemory> KernelSystem::CreateSharedMemoryForApplet(
u32 offset, u32 size, MemoryPermission permissions, MemoryPermission other_permissions,
std::string name) {
auto shared_memory{std::make_shared<SharedMemory>()};
auto shared_memory{std::make_shared<SharedMemory>(*this)};
// Allocate memory in heap
MemoryRegionInfo* memory_region = GetMemoryRegion(MemoryRegion::SYSTEM);

View file

@ -16,7 +16,7 @@ namespace Kernel {
class SharedMemory final : public Object {
public:
explicit SharedMemory();
explicit SharedMemory(KernelSystem& kernel);
~SharedMemory() override;
std::string GetTypeName() const override {
@ -123,3 +123,6 @@ private:
};
} // namespace Kernel
BOOST_CLASS_EXPORT_KEY(Kernel::SharedMemory)
CONSTRUCT_KERNEL_OBJECT(Kernel::SharedMemory)

View file

@ -66,9 +66,9 @@ u32 ThreadManager::NewThreadId() {
return next_thread_id++;
}
Thread::Thread()
: context(Core::Global<KernelSystem>().GetThreadManager().NewContext()),
thread_manager(Core::Global<KernelSystem>().GetThreadManager()) {}
Thread::Thread(KernelSystem& kernel)
: WaitObject(kernel), context(kernel.GetThreadManager().NewContext()),
thread_manager(kernel.GetThreadManager()) {}
Thread::~Thread() {}
Thread* ThreadManager::GetCurrentThread() const {
@ -338,8 +338,7 @@ ResultVal<std::shared_ptr<Thread>> KernelSystem::CreateThread(std::string name,
ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
}
auto thread{std::make_shared<Thread>()};
thread->Init(*this);
auto thread{std::make_shared<Thread>(*this)};
thread_manager->thread_list.push_back(thread);
thread_manager->ready_queue.prepare(priority);

View file

@ -164,7 +164,7 @@ private:
class Thread final : public WaitObject {
public:
explicit Thread();
explicit Thread(KernelSystem&);
~Thread() override;
std::string GetName() const override {
@ -340,3 +340,4 @@ std::shared_ptr<Thread> SetupMainThread(KernelSystem& kernel, u32 entry_point, u
} // namespace Kernel
BOOST_CLASS_EXPORT_KEY(Kernel::Thread)
CONSTRUCT_KERNEL_OBJECT(Kernel::Thread)

View file

@ -4,6 +4,7 @@
#include <cinttypes>
#include <unordered_map>
#include "common/archives.h"
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
@ -13,17 +14,19 @@
#include "core/hle/kernel/timer.h"
#include "core/global.h"
SERIALIZE_EXPORT_IMPL(Kernel::Timer)
namespace Kernel {
Timer::Timer() : kernel(Core::Global<KernelSystem>()), timer_manager(Core::Global<KernelSystem>().GetTimerManager()) {}
Timer::Timer(KernelSystem& kernel)
: WaitObject(kernel), kernel(kernel), timer_manager(kernel.GetTimerManager()) {}
Timer::~Timer() {
Cancel();
timer_manager.timer_callback_table.erase(callback_id);
}
std::shared_ptr<Timer> KernelSystem::CreateTimer(ResetType reset_type, std::string name) {
auto timer{std::make_shared<Timer>()};
timer->Init(*this);
auto timer{std::make_shared<Timer>(*this)};
timer->reset_type = reset_type;
timer->signaled = false;

View file

@ -46,7 +46,7 @@ private:
class Timer final : public WaitObject {
public:
explicit Timer();
explicit Timer(KernelSystem& kernel);
~Timer() override;
std::string GetTypeName() const override {
@ -127,3 +127,6 @@ private:
};
} // namespace Kernel
BOOST_CLASS_EXPORT_KEY(Kernel::Timer)
CONSTRUCT_KERNEL_OBJECT(Kernel::Timer)