Kernel: replace boost::intrusive_ptr with std::shared_ptr
This commit is contained in:
parent
c1de8acfe5
commit
5f11c5f733
96 changed files with 522 additions and 538 deletions
|
@ -123,8 +123,8 @@ QString WaitTreeWaitObject::GetResetTypeQString(Kernel::ResetType reset_type) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
WaitTreeObjectList::WaitTreeObjectList(
|
WaitTreeObjectList::WaitTreeObjectList(const std::vector<std::shared_ptr<Kernel::WaitObject>>& list,
|
||||||
const std::vector<Kernel::SharedPtr<Kernel::WaitObject>>& list, bool w_all)
|
bool w_all)
|
||||||
: object_list(list), wait_all(w_all) {}
|
: object_list(list), wait_all(w_all) {}
|
||||||
|
|
||||||
QString WaitTreeObjectList::GetText() const {
|
QString WaitTreeObjectList::GetText() const {
|
||||||
|
@ -311,7 +311,7 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeTimer::GetChildren() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
WaitTreeMutexList::WaitTreeMutexList(
|
WaitTreeMutexList::WaitTreeMutexList(
|
||||||
const boost::container::flat_set<Kernel::SharedPtr<Kernel::Mutex>>& list)
|
const boost::container::flat_set<std::shared_ptr<Kernel::Mutex>>& list)
|
||||||
: mutex_list(list) {}
|
: mutex_list(list) {}
|
||||||
|
|
||||||
QString WaitTreeMutexList::GetText() const {
|
QString WaitTreeMutexList::GetText() const {
|
||||||
|
@ -325,7 +325,7 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeMutexList::GetChildren() cons
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
WaitTreeThreadList::WaitTreeThreadList(const std::vector<Kernel::SharedPtr<Kernel::Thread>>& list)
|
WaitTreeThreadList::WaitTreeThreadList(const std::vector<std::shared_ptr<Kernel::Thread>>& list)
|
||||||
: thread_list(list) {}
|
: thread_list(list) {}
|
||||||
|
|
||||||
QString WaitTreeThreadList::GetText() const {
|
QString WaitTreeThreadList::GetText() const {
|
||||||
|
|
|
@ -82,13 +82,12 @@ protected:
|
||||||
class WaitTreeObjectList : public WaitTreeExpandableItem {
|
class WaitTreeObjectList : public WaitTreeExpandableItem {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
WaitTreeObjectList(const std::vector<Kernel::SharedPtr<Kernel::WaitObject>>& list,
|
WaitTreeObjectList(const std::vector<std::shared_ptr<Kernel::WaitObject>>& list, bool wait_all);
|
||||||
bool wait_all);
|
|
||||||
QString GetText() const override;
|
QString GetText() const override;
|
||||||
std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
|
std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::vector<Kernel::SharedPtr<Kernel::WaitObject>>& object_list;
|
const std::vector<std::shared_ptr<Kernel::WaitObject>>& object_list;
|
||||||
bool wait_all;
|
bool wait_all;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -133,24 +132,24 @@ class WaitTreeMutexList : public WaitTreeExpandableItem {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit WaitTreeMutexList(
|
explicit WaitTreeMutexList(
|
||||||
const boost::container::flat_set<Kernel::SharedPtr<Kernel::Mutex>>& list);
|
const boost::container::flat_set<std::shared_ptr<Kernel::Mutex>>& list);
|
||||||
|
|
||||||
QString GetText() const override;
|
QString GetText() const override;
|
||||||
std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
|
std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const boost::container::flat_set<Kernel::SharedPtr<Kernel::Mutex>>& mutex_list;
|
const boost::container::flat_set<std::shared_ptr<Kernel::Mutex>>& mutex_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WaitTreeThreadList : public WaitTreeExpandableItem {
|
class WaitTreeThreadList : public WaitTreeExpandableItem {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit WaitTreeThreadList(const std::vector<Kernel::SharedPtr<Kernel::Thread>>& list);
|
explicit WaitTreeThreadList(const std::vector<std::shared_ptr<Kernel::Thread>>& list);
|
||||||
QString GetText() const override;
|
QString GetText() const override;
|
||||||
std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
|
std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::vector<Kernel::SharedPtr<Kernel::Thread>>& thread_list;
|
const std::vector<std::shared_ptr<Kernel::Thread>>& thread_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WaitTreeModel : public QAbstractItemModel {
|
class WaitTreeModel : public QAbstractItemModel {
|
||||||
|
|
|
@ -125,7 +125,7 @@ System::ResultStatus System::Load(EmuWindow& emu_window, const std::string& file
|
||||||
return init_result;
|
return init_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Kernel::SharedPtr<Kernel::Process> process;
|
std::shared_ptr<Kernel::Process> process;
|
||||||
const Loader::ResultStatus load_result{app_loader->Load(process)};
|
const Loader::ResultStatus load_result{app_loader->Load(process)};
|
||||||
kernel->SetCurrentProcess(process);
|
kernel->SetCurrentProcess(process);
|
||||||
if (Loader::ResultStatus::Success != load_result) {
|
if (Loader::ResultStatus::Success != load_result) {
|
||||||
|
|
|
@ -22,7 +22,7 @@ private:
|
||||||
/// This SharedMemory will be created when we receive the LibAppJustStarted message.
|
/// This SharedMemory will be created when we receive the LibAppJustStarted message.
|
||||||
/// It holds the framebuffer info retrieved by the application with
|
/// It holds the framebuffer info retrieved by the application with
|
||||||
/// GSPGPU::ImportDisplayCaptureInfo
|
/// GSPGPU::ImportDisplayCaptureInfo
|
||||||
Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory;
|
std::shared_ptr<Kernel::SharedMemory> framebuffer_memory;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace HLE::Applets
|
} // namespace HLE::Applets
|
||||||
|
|
|
@ -121,7 +121,7 @@ private:
|
||||||
/// This SharedMemory will be created when we receive the LibAppJustStarted message.
|
/// This SharedMemory will be created when we receive the LibAppJustStarted message.
|
||||||
/// It holds the framebuffer info retrieved by the application with
|
/// It holds the framebuffer info retrieved by the application with
|
||||||
/// GSPGPU::ImportDisplayCaptureInfo
|
/// GSPGPU::ImportDisplayCaptureInfo
|
||||||
Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory;
|
std::shared_ptr<Kernel::SharedMemory> framebuffer_memory;
|
||||||
|
|
||||||
MiiConfig config;
|
MiiConfig config;
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,7 +22,7 @@ private:
|
||||||
/// This SharedMemory will be created when we receive the Request message.
|
/// This SharedMemory will be created when we receive the Request message.
|
||||||
/// It holds the framebuffer info retrieved by the application with
|
/// It holds the framebuffer info retrieved by the application with
|
||||||
/// GSPGPU::ImportDisplayCaptureInfo
|
/// GSPGPU::ImportDisplayCaptureInfo
|
||||||
Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory;
|
std::shared_ptr<Kernel::SharedMemory> framebuffer_memory;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace HLE::Applets
|
} // namespace HLE::Applets
|
||||||
|
|
|
@ -60,8 +60,7 @@ ResultCode SoftwareKeyboard::StartImpl(Service::APT::AppletStartupParameter cons
|
||||||
"The size of the parameter (SoftwareKeyboardConfig) is wrong");
|
"The size of the parameter (SoftwareKeyboardConfig) is wrong");
|
||||||
|
|
||||||
memcpy(&config, parameter.buffer.data(), parameter.buffer.size());
|
memcpy(&config, parameter.buffer.data(), parameter.buffer.size());
|
||||||
text_memory =
|
text_memory = std::static_pointer_cast<Kernel::SharedMemory, Kernel::Object>(parameter.object);
|
||||||
boost::static_pointer_cast<Kernel::SharedMemory, Kernel::Object>(parameter.object);
|
|
||||||
|
|
||||||
// TODO(Subv): Verify if this is the correct behavior
|
// TODO(Subv): Verify if this is the correct behavior
|
||||||
memset(text_memory->GetPointer(), 0, text_memory->GetSize());
|
memset(text_memory->GetPointer(), 0, text_memory->GetSize());
|
||||||
|
|
|
@ -199,10 +199,10 @@ private:
|
||||||
/// This SharedMemory will be created when we receive the LibAppJustStarted message.
|
/// This SharedMemory will be created when we receive the LibAppJustStarted message.
|
||||||
/// It holds the framebuffer info retrieved by the application with
|
/// It holds the framebuffer info retrieved by the application with
|
||||||
/// GSPGPU::ImportDisplayCaptureInfo
|
/// GSPGPU::ImportDisplayCaptureInfo
|
||||||
Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory;
|
std::shared_ptr<Kernel::SharedMemory> framebuffer_memory;
|
||||||
|
|
||||||
/// SharedMemory where the output text will be stored
|
/// SharedMemory where the output text will be stored
|
||||||
Kernel::SharedPtr<Kernel::SharedMemory> text_memory;
|
std::shared_ptr<Kernel::SharedMemory> text_memory;
|
||||||
|
|
||||||
/// Configuration of this instance of the SoftwareKeyboard, as received from the application
|
/// Configuration of this instance of the SoftwareKeyboard, as received from the application
|
||||||
SoftwareKeyboardConfig config;
|
SoftwareKeyboardConfig config;
|
||||||
|
|
|
@ -88,10 +88,10 @@ public:
|
||||||
|
|
||||||
// TODO : ensure that translate params are added after all regular params
|
// TODO : ensure that translate params are added after all regular params
|
||||||
template <typename... O>
|
template <typename... O>
|
||||||
void PushCopyObjects(Kernel::SharedPtr<O>... pointers);
|
void PushCopyObjects(std::shared_ptr<O>... pointers);
|
||||||
|
|
||||||
template <typename... O>
|
template <typename... O>
|
||||||
void PushMoveObjects(Kernel::SharedPtr<O>... pointers);
|
void PushMoveObjects(std::shared_ptr<O>... pointers);
|
||||||
|
|
||||||
void PushStaticBuffer(const std::vector<u8>& buffer, u8 buffer_id);
|
void PushStaticBuffer(const std::vector<u8>& buffer, u8 buffer_id);
|
||||||
|
|
||||||
|
@ -170,12 +170,12 @@ inline void RequestBuilder::PushMoveHLEHandles(H... handles) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... O>
|
template <typename... O>
|
||||||
inline void RequestBuilder::PushCopyObjects(Kernel::SharedPtr<O>... pointers) {
|
inline void RequestBuilder::PushCopyObjects(std::shared_ptr<O>... pointers) {
|
||||||
PushCopyHLEHandles(context->AddOutgoingHandle(std::move(pointers))...);
|
PushCopyHLEHandles(context->AddOutgoingHandle(std::move(pointers))...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... O>
|
template <typename... O>
|
||||||
inline void RequestBuilder::PushMoveObjects(Kernel::SharedPtr<O>... pointers) {
|
inline void RequestBuilder::PushMoveObjects(std::shared_ptr<O>... pointers) {
|
||||||
PushMoveHLEHandles(context->AddOutgoingHandle(std::move(pointers))...);
|
PushMoveHLEHandles(context->AddOutgoingHandle(std::move(pointers))...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,11 +233,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Equivalent to calling `PopGenericObjects<1>()[0]`.
|
/// Equivalent to calling `PopGenericObjects<1>()[0]`.
|
||||||
Kernel::SharedPtr<Kernel::Object> PopGenericObject();
|
std::shared_ptr<Kernel::Object> PopGenericObject();
|
||||||
|
|
||||||
/// Equivalent to calling `std::get<0>(PopObjects<T>())`.
|
/// Equivalent to calling `std::get<0>(PopObjects<T>())`.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Kernel::SharedPtr<T> PopObject();
|
std::shared_ptr<T> PopObject();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pop a descriptor containing `N` handles and resolves them to Kernel::Object pointers. If a
|
* Pop a descriptor containing `N` handles and resolves them to Kernel::Object pointers. If a
|
||||||
|
@ -247,7 +247,7 @@ public:
|
||||||
* call to read 2 single-handle descriptors.
|
* call to read 2 single-handle descriptors.
|
||||||
*/
|
*/
|
||||||
template <unsigned int N>
|
template <unsigned int N>
|
||||||
std::array<Kernel::SharedPtr<Kernel::Object>, N> PopGenericObjects();
|
std::array<std::shared_ptr<Kernel::Object>, N> PopGenericObjects();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves handles to Kernel::Objects as in PopGenericsObjects(), but then also casts them to
|
* Resolves handles to Kernel::Objects as in PopGenericsObjects(), but then also casts them to
|
||||||
|
@ -255,11 +255,11 @@ public:
|
||||||
* not match, null is returned instead.
|
* not match, null is returned instead.
|
||||||
*/
|
*/
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
std::tuple<Kernel::SharedPtr<T>...> PopObjects();
|
std::tuple<std::shared_ptr<T>...> PopObjects();
|
||||||
|
|
||||||
/// Convenience wrapper around PopObjects() which assigns the handles to the passed references.
|
/// Convenience wrapper around PopObjects() which assigns the handles to the passed references.
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
void PopObjects(Kernel::SharedPtr<T>&... pointers) {
|
void PopObjects(std::shared_ptr<T>&... pointers) {
|
||||||
std::tie(pointers...) = PopObjects<T...>();
|
std::tie(pointers...) = PopObjects<T...>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,20 +377,20 @@ std::array<u32, N> RequestParser::PopHLEHandles() {
|
||||||
return handles;
|
return handles;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Kernel::SharedPtr<Kernel::Object> RequestParser::PopGenericObject() {
|
inline std::shared_ptr<Kernel::Object> RequestParser::PopGenericObject() {
|
||||||
auto [handle] = PopHLEHandles<1>();
|
auto [handle] = PopHLEHandles<1>();
|
||||||
return context->GetIncomingHandle(handle);
|
return context->GetIncomingHandle(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Kernel::SharedPtr<T> RequestParser::PopObject() {
|
std::shared_ptr<T> RequestParser::PopObject() {
|
||||||
return Kernel::DynamicObjectCast<T>(PopGenericObject());
|
return Kernel::DynamicObjectCast<T>(PopGenericObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <unsigned int N>
|
template <unsigned int N>
|
||||||
inline std::array<Kernel::SharedPtr<Kernel::Object>, N> RequestParser::PopGenericObjects() {
|
inline std::array<std::shared_ptr<Kernel::Object>, N> RequestParser::PopGenericObjects() {
|
||||||
std::array<u32, N> handles = PopHLEHandles<N>();
|
std::array<u32, N> handles = PopHLEHandles<N>();
|
||||||
std::array<Kernel::SharedPtr<Kernel::Object>, N> pointers;
|
std::array<std::shared_ptr<Kernel::Object>, N> pointers;
|
||||||
for (int i = 0; i < N; ++i) {
|
for (int i = 0; i < N; ++i) {
|
||||||
pointers[i] = context->GetIncomingHandle(handles[i]);
|
pointers[i] = context->GetIncomingHandle(handles[i]);
|
||||||
}
|
}
|
||||||
|
@ -399,15 +399,15 @@ inline std::array<Kernel::SharedPtr<Kernel::Object>, N> RequestParser::PopGeneri
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template <typename... T, std::size_t... I>
|
template <typename... T, std::size_t... I>
|
||||||
std::tuple<Kernel::SharedPtr<T>...> PopObjectsHelper(
|
std::tuple<std::shared_ptr<T>...> PopObjectsHelper(
|
||||||
std::array<Kernel::SharedPtr<Kernel::Object>, sizeof...(T)>&& pointers,
|
std::array<std::shared_ptr<Kernel::Object>, sizeof...(T)>&& pointers,
|
||||||
std::index_sequence<I...>) {
|
std::index_sequence<I...>) {
|
||||||
return std::make_tuple(Kernel::DynamicObjectCast<T>(std::move(pointers[I]))...);
|
return std::make_tuple(Kernel::DynamicObjectCast<T>(std::move(pointers[I]))...);
|
||||||
}
|
}
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
inline std::tuple<Kernel::SharedPtr<T>...> RequestParser::PopObjects() {
|
inline std::tuple<std::shared_ptr<T>...> RequestParser::PopObjects() {
|
||||||
return detail::PopObjectsHelper<T...>(PopGenericObjects<sizeof...(T)>(),
|
return detail::PopObjectsHelper<T...>(PopGenericObjects<sizeof...(T)>(),
|
||||||
std::index_sequence_for<T...>{});
|
std::index_sequence_for<T...>{});
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
void AddressArbiter::WaitThread(SharedPtr<Thread> thread, VAddr wait_address) {
|
void AddressArbiter::WaitThread(std::shared_ptr<Thread> thread, VAddr wait_address) {
|
||||||
thread->wait_address = wait_address;
|
thread->wait_address = wait_address;
|
||||||
thread->status = ThreadStatus::WaitArb;
|
thread->status = ThreadStatus::WaitArb;
|
||||||
waiting_threads.emplace_back(std::move(thread));
|
waiting_threads.emplace_back(std::move(thread));
|
||||||
|
@ -38,7 +38,7 @@ void AddressArbiter::ResumeAllThreads(VAddr address) {
|
||||||
waiting_threads.erase(itr, waiting_threads.end());
|
waiting_threads.erase(itr, waiting_threads.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<Thread> AddressArbiter::ResumeHighestPriorityThread(VAddr address) {
|
std::shared_ptr<Thread> AddressArbiter::ResumeHighestPriorityThread(VAddr address) {
|
||||||
// Determine which threads are waiting on this address, those should be considered for wakeup.
|
// Determine which threads are waiting on this address, those should be considered for wakeup.
|
||||||
auto matches_start = std::stable_partition(
|
auto matches_start = std::stable_partition(
|
||||||
waiting_threads.begin(), waiting_threads.end(), [address](const auto& thread) {
|
waiting_threads.begin(), waiting_threads.end(), [address](const auto& thread) {
|
||||||
|
@ -68,19 +68,19 @@ SharedPtr<Thread> AddressArbiter::ResumeHighestPriorityThread(VAddr address) {
|
||||||
AddressArbiter::AddressArbiter(KernelSystem& kernel) : Object(kernel), kernel(kernel) {}
|
AddressArbiter::AddressArbiter(KernelSystem& kernel) : Object(kernel), kernel(kernel) {}
|
||||||
AddressArbiter::~AddressArbiter() {}
|
AddressArbiter::~AddressArbiter() {}
|
||||||
|
|
||||||
SharedPtr<AddressArbiter> KernelSystem::CreateAddressArbiter(std::string name) {
|
std::shared_ptr<AddressArbiter> KernelSystem::CreateAddressArbiter(std::string name) {
|
||||||
SharedPtr<AddressArbiter> address_arbiter(new AddressArbiter(*this));
|
auto address_arbiter{std::make_shared<AddressArbiter>(*this)};
|
||||||
|
|
||||||
address_arbiter->name = std::move(name);
|
address_arbiter->name = std::move(name);
|
||||||
|
|
||||||
return address_arbiter;
|
return address_arbiter;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode AddressArbiter::ArbitrateAddress(SharedPtr<Thread> thread, ArbitrationType type,
|
ResultCode AddressArbiter::ArbitrateAddress(std::shared_ptr<Thread> thread, ArbitrationType type,
|
||||||
VAddr address, s32 value, u64 nanoseconds) {
|
VAddr address, s32 value, u64 nanoseconds) {
|
||||||
|
|
||||||
auto timeout_callback = [this](ThreadWakeupReason reason, SharedPtr<Thread> thread,
|
auto timeout_callback = [this](ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||||
SharedPtr<WaitObject> object) {
|
std::shared_ptr<WaitObject> object) {
|
||||||
ASSERT(reason == ThreadWakeupReason::Timeout);
|
ASSERT(reason == ThreadWakeupReason::Timeout);
|
||||||
// Remove the newly-awakened thread from the Arbiter's waiting list.
|
// Remove the newly-awakened thread from the Arbiter's waiting list.
|
||||||
waiting_threads.erase(std::remove(waiting_threads.begin(), waiting_threads.end(), thread),
|
waiting_threads.erase(std::remove(waiting_threads.begin(), waiting_threads.end(), thread),
|
||||||
|
|
|
@ -31,6 +31,9 @@ enum class ArbitrationType : u32 {
|
||||||
|
|
||||||
class AddressArbiter final : public Object {
|
class AddressArbiter final : public Object {
|
||||||
public:
|
public:
|
||||||
|
explicit AddressArbiter(KernelSystem& kernel);
|
||||||
|
~AddressArbiter() override;
|
||||||
|
|
||||||
std::string GetTypeName() const override {
|
std::string GetTypeName() const override {
|
||||||
return "Arbiter";
|
return "Arbiter";
|
||||||
}
|
}
|
||||||
|
@ -45,29 +48,24 @@ public:
|
||||||
|
|
||||||
std::string name; ///< Name of address arbiter object (optional)
|
std::string name; ///< Name of address arbiter object (optional)
|
||||||
|
|
||||||
ResultCode ArbitrateAddress(SharedPtr<Thread> thread, ArbitrationType type, VAddr address,
|
ResultCode ArbitrateAddress(std::shared_ptr<Thread> thread, ArbitrationType type, VAddr address,
|
||||||
s32 value, u64 nanoseconds);
|
s32 value, u64 nanoseconds);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit AddressArbiter(KernelSystem& kernel);
|
|
||||||
~AddressArbiter() override;
|
|
||||||
|
|
||||||
KernelSystem& kernel;
|
KernelSystem& kernel;
|
||||||
|
|
||||||
/// Puts the thread to wait on the specified arbitration address under this address arbiter.
|
/// Puts the thread to wait on the specified arbitration address under this address arbiter.
|
||||||
void WaitThread(SharedPtr<Thread> thread, VAddr wait_address);
|
void WaitThread(std::shared_ptr<Thread> thread, VAddr wait_address);
|
||||||
|
|
||||||
/// Resume all threads found to be waiting on the address under this address arbiter
|
/// Resume all threads found to be waiting on the address under this address arbiter
|
||||||
void ResumeAllThreads(VAddr address);
|
void ResumeAllThreads(VAddr address);
|
||||||
|
|
||||||
/// Resume one thread found to be waiting on the address under this address arbiter and return
|
/// Resume one thread found to be waiting on the address under this address arbiter and return
|
||||||
/// the resumed thread.
|
/// the resumed thread.
|
||||||
SharedPtr<Thread> ResumeHighestPriorityThread(VAddr address);
|
std::shared_ptr<Thread> ResumeHighestPriorityThread(VAddr address);
|
||||||
|
|
||||||
/// Threads waiting for the address arbiter to be signaled.
|
/// Threads waiting for the address arbiter to be signaled.
|
||||||
std::vector<SharedPtr<Thread>> waiting_threads;
|
std::vector<std::shared_ptr<Thread>> waiting_threads;
|
||||||
|
|
||||||
friend class KernelSystem;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace Kernel {
|
||||||
ClientPort::ClientPort(KernelSystem& kernel) : kernel(kernel), Object(kernel) {}
|
ClientPort::ClientPort(KernelSystem& kernel) : kernel(kernel), Object(kernel) {}
|
||||||
ClientPort::~ClientPort() = default;
|
ClientPort::~ClientPort() = default;
|
||||||
|
|
||||||
ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() {
|
ResultVal<std::shared_ptr<ClientSession>> ClientPort::Connect() {
|
||||||
// Note: Threads do not wait for the server endpoint to call
|
// Note: Threads do not wait for the server endpoint to call
|
||||||
// AcceptSession before returning from this call.
|
// AcceptSession before returning from this call.
|
||||||
|
|
||||||
|
@ -26,17 +26,18 @@ ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() {
|
||||||
active_sessions++;
|
active_sessions++;
|
||||||
|
|
||||||
// Create a new session pair, let the created sessions inherit the parent port's HLE handler.
|
// Create a new session pair, let the created sessions inherit the parent port's HLE handler.
|
||||||
auto sessions = kernel.CreateSessionPair(server_port->GetName(), this);
|
auto sessions = kernel.CreateSessionPair(server_port->GetName(), SharedFrom(this));
|
||||||
|
|
||||||
if (server_port->hle_handler)
|
if (server_port->hle_handler)
|
||||||
server_port->hle_handler->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions));
|
server_port->hle_handler->ClientConnected(
|
||||||
|
std::get<std::shared_ptr<ServerSession>>(sessions));
|
||||||
else
|
else
|
||||||
server_port->pending_sessions.push_back(std::get<SharedPtr<ServerSession>>(sessions));
|
server_port->pending_sessions.push_back(std::get<std::shared_ptr<ServerSession>>(sessions));
|
||||||
|
|
||||||
// Wake the threads waiting on the ServerPort
|
// Wake the threads waiting on the ServerPort
|
||||||
server_port->WakeupAllWaitingThreads();
|
server_port->WakeupAllWaitingThreads();
|
||||||
|
|
||||||
return MakeResult(std::get<SharedPtr<ClientSession>>(sessions));
|
return MakeResult(std::get<std::shared_ptr<ClientSession>>(sessions));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientPort::ConnectionClosed() {
|
void ClientPort::ConnectionClosed() {
|
||||||
|
|
|
@ -16,6 +16,9 @@ class ClientSession;
|
||||||
|
|
||||||
class ClientPort final : public Object {
|
class ClientPort final : public Object {
|
||||||
public:
|
public:
|
||||||
|
explicit ClientPort(KernelSystem& kernel);
|
||||||
|
~ClientPort() override;
|
||||||
|
|
||||||
friend class ServerPort;
|
friend class ServerPort;
|
||||||
std::string GetTypeName() const override {
|
std::string GetTypeName() const override {
|
||||||
return "ClientPort";
|
return "ClientPort";
|
||||||
|
@ -29,7 +32,7 @@ public:
|
||||||
return HANDLE_TYPE;
|
return HANDLE_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<ServerPort> GetServerPort() const {
|
std::shared_ptr<ServerPort> GetServerPort() const {
|
||||||
return server_port;
|
return server_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +42,7 @@ public:
|
||||||
* waiting on it to awake.
|
* waiting on it to awake.
|
||||||
* @returns ClientSession The client endpoint of the created Session pair, or error code.
|
* @returns ClientSession The client endpoint of the created Session pair, or error code.
|
||||||
*/
|
*/
|
||||||
ResultVal<SharedPtr<ClientSession>> Connect();
|
ResultVal<std::shared_ptr<ClientSession>> Connect();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signifies that a previously active connection has been closed,
|
* Signifies that a previously active connection has been closed,
|
||||||
|
@ -48,11 +51,8 @@ public:
|
||||||
void ConnectionClosed();
|
void ConnectionClosed();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit ClientPort(KernelSystem& kernel);
|
|
||||||
~ClientPort() override;
|
|
||||||
|
|
||||||
KernelSystem& kernel;
|
KernelSystem& kernel;
|
||||||
SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port.
|
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 max_sessions = 0; ///< Maximum number of simultaneous sessions the port can have
|
||||||
u32 active_sessions = 0; ///< Number of currently open sessions to this port
|
u32 active_sessions = 0; ///< Number of currently open sessions to this port
|
||||||
std::string name; ///< Name of client port (optional)
|
std::string name; ///< Name of client port (optional)
|
||||||
|
|
|
@ -20,7 +20,7 @@ ClientSession::~ClientSession() {
|
||||||
|
|
||||||
// Local references to ServerSession and SessionRequestHandler are necessary to guarantee they
|
// Local references to ServerSession and SessionRequestHandler are necessary to guarantee they
|
||||||
// will be kept alive until after ClientDisconnected() returns.
|
// will be kept alive until after ClientDisconnected() returns.
|
||||||
SharedPtr<ServerSession> server = parent->server;
|
std::shared_ptr<ServerSession> server = SharedFrom(parent->server);
|
||||||
if (server) {
|
if (server) {
|
||||||
std::shared_ptr<SessionRequestHandler> hle_handler = server->hle_handler;
|
std::shared_ptr<SessionRequestHandler> hle_handler = server->hle_handler;
|
||||||
if (hle_handler)
|
if (hle_handler)
|
||||||
|
@ -42,9 +42,9 @@ ClientSession::~ClientSession() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode ClientSession::SendSyncRequest(SharedPtr<Thread> thread) {
|
ResultCode ClientSession::SendSyncRequest(std::shared_ptr<Thread> thread) {
|
||||||
// Keep ServerSession alive until we're done working with it.
|
// Keep ServerSession alive until we're done working with it.
|
||||||
SharedPtr<ServerSession> server = parent->server;
|
std::shared_ptr<ServerSession> server = SharedFrom(parent->server);
|
||||||
if (server == nullptr)
|
if (server == nullptr)
|
||||||
return ERR_SESSION_CLOSED_BY_REMOTE;
|
return ERR_SESSION_CLOSED_BY_REMOTE;
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,9 @@ class Thread;
|
||||||
|
|
||||||
class ClientSession final : public Object {
|
class ClientSession final : public Object {
|
||||||
public:
|
public:
|
||||||
|
explicit ClientSession(KernelSystem& kernel);
|
||||||
|
~ClientSession() override;
|
||||||
|
|
||||||
friend class KernelSystem;
|
friend class KernelSystem;
|
||||||
|
|
||||||
std::string GetTypeName() const override {
|
std::string GetTypeName() const override {
|
||||||
|
@ -37,16 +40,12 @@ public:
|
||||||
* @param thread Thread that initiated the request.
|
* @param thread Thread that initiated the request.
|
||||||
* @return ResultCode of the operation.
|
* @return ResultCode of the operation.
|
||||||
*/
|
*/
|
||||||
ResultCode SendSyncRequest(SharedPtr<Thread> thread);
|
ResultCode SendSyncRequest(std::shared_ptr<Thread> thread);
|
||||||
|
|
||||||
std::string name; ///< Name of client port (optional)
|
std::string name; ///< Name of client port (optional)
|
||||||
|
|
||||||
/// The parent session, which links to the server endpoint.
|
/// The parent session, which links to the server endpoint.
|
||||||
std::shared_ptr<Session> parent;
|
std::shared_ptr<Session> parent;
|
||||||
|
|
||||||
private:
|
|
||||||
explicit ClientSession(KernelSystem& kernel);
|
|
||||||
~ClientSession() override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
|
|
@ -15,8 +15,8 @@ namespace Kernel {
|
||||||
Event::Event(KernelSystem& kernel) : WaitObject(kernel) {}
|
Event::Event(KernelSystem& kernel) : WaitObject(kernel) {}
|
||||||
Event::~Event() {}
|
Event::~Event() {}
|
||||||
|
|
||||||
SharedPtr<Event> KernelSystem::CreateEvent(ResetType reset_type, std::string name) {
|
std::shared_ptr<Event> KernelSystem::CreateEvent(ResetType reset_type, std::string name) {
|
||||||
SharedPtr<Event> evt(new Event(*this));
|
auto evt{std::make_shared<Event>(*this)};
|
||||||
|
|
||||||
evt->signaled = false;
|
evt->signaled = false;
|
||||||
evt->reset_type = reset_type;
|
evt->reset_type = reset_type;
|
||||||
|
|
|
@ -12,6 +12,9 @@ namespace Kernel {
|
||||||
|
|
||||||
class Event final : public WaitObject {
|
class Event final : public WaitObject {
|
||||||
public:
|
public:
|
||||||
|
explicit Event(KernelSystem& kernel);
|
||||||
|
~Event() override;
|
||||||
|
|
||||||
std::string GetTypeName() const override {
|
std::string GetTypeName() const override {
|
||||||
return "Event";
|
return "Event";
|
||||||
}
|
}
|
||||||
|
@ -40,9 +43,6 @@ public:
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit Event(KernelSystem& kernel);
|
|
||||||
~Event() override;
|
|
||||||
|
|
||||||
ResetType reset_type; ///< Current ResetType
|
ResetType reset_type; ///< Current ResetType
|
||||||
|
|
||||||
bool signaled; ///< Whether the event has already been signaled
|
bool signaled; ///< Whether the event has already been signaled
|
||||||
|
|
|
@ -28,7 +28,7 @@ HandleTable::HandleTable(KernelSystem& kernel) : kernel(kernel) {
|
||||||
|
|
||||||
HandleTable::~HandleTable() = default;
|
HandleTable::~HandleTable() = default;
|
||||||
|
|
||||||
ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
|
ResultVal<Handle> HandleTable::Create(std::shared_ptr<Object> obj) {
|
||||||
DEBUG_ASSERT(obj != nullptr);
|
DEBUG_ASSERT(obj != nullptr);
|
||||||
|
|
||||||
u16 slot = next_free_slot;
|
u16 slot = next_free_slot;
|
||||||
|
@ -53,7 +53,7 @@ ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
|
ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
|
||||||
SharedPtr<Object> object = GetGeneric(handle);
|
std::shared_ptr<Object> object = GetGeneric(handle);
|
||||||
if (object == nullptr) {
|
if (object == nullptr) {
|
||||||
LOG_ERROR(Kernel, "Tried to duplicate invalid handle: {:08X}", handle);
|
LOG_ERROR(Kernel, "Tried to duplicate invalid handle: {:08X}", handle);
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
@ -81,9 +81,9 @@ bool HandleTable::IsValid(Handle handle) const {
|
||||||
return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation;
|
return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const {
|
std::shared_ptr<Object> HandleTable::GetGeneric(Handle handle) const {
|
||||||
if (handle == CurrentThread) {
|
if (handle == CurrentThread) {
|
||||||
return kernel.GetThreadManager().GetCurrentThread();
|
return SharedFrom(kernel.GetThreadManager().GetCurrentThread());
|
||||||
} else if (handle == CurrentProcess) {
|
} else if (handle == CurrentProcess) {
|
||||||
return kernel.GetCurrentProcess();
|
return kernel.GetCurrentProcess();
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ public:
|
||||||
* @return The created Handle or one of the following errors:
|
* @return The created Handle or one of the following errors:
|
||||||
* - `ERR_OUT_OF_HANDLES`: the maximum number of handles has been exceeded.
|
* - `ERR_OUT_OF_HANDLES`: the maximum number of handles has been exceeded.
|
||||||
*/
|
*/
|
||||||
ResultVal<Handle> Create(SharedPtr<Object> obj);
|
ResultVal<Handle> Create(std::shared_ptr<Object> obj);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new handle that points to the same object as the passed in handle.
|
* Returns a new handle that points to the same object as the passed in handle.
|
||||||
|
@ -74,7 +74,7 @@ public:
|
||||||
* Looks up a handle.
|
* Looks up a handle.
|
||||||
* @return Pointer to the looked-up object, or `nullptr` if the handle is not valid.
|
* @return Pointer to the looked-up object, or `nullptr` if the handle is not valid.
|
||||||
*/
|
*/
|
||||||
SharedPtr<Object> GetGeneric(Handle handle) const;
|
std::shared_ptr<Object> GetGeneric(Handle handle) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Looks up a handle while verifying its type.
|
* Looks up a handle while verifying its type.
|
||||||
|
@ -82,7 +82,7 @@ public:
|
||||||
* type differs from the requested one.
|
* type differs from the requested one.
|
||||||
*/
|
*/
|
||||||
template <class T>
|
template <class T>
|
||||||
SharedPtr<T> Get(Handle handle) const {
|
std::shared_ptr<T> Get(Handle handle) const {
|
||||||
return DynamicObjectCast<T>(GetGeneric(handle));
|
return DynamicObjectCast<T>(GetGeneric(handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ private:
|
||||||
static const std::size_t MAX_COUNT = 4096;
|
static const std::size_t MAX_COUNT = 4096;
|
||||||
|
|
||||||
/// Stores the Object referenced by the handle or null if the slot is empty.
|
/// Stores the Object referenced by the handle or null if the slot is empty.
|
||||||
std::array<SharedPtr<Object>, MAX_COUNT> objects;
|
std::array<std::shared_ptr<Object>, MAX_COUNT> objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The value of `next_generation` when the handle was created, used to check for validity. For
|
* The value of `next_generation` when the handle was created, used to check for validity. For
|
||||||
|
|
|
@ -15,16 +15,16 @@
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
SessionRequestHandler::SessionInfo::SessionInfo(SharedPtr<ServerSession> session,
|
SessionRequestHandler::SessionInfo::SessionInfo(std::shared_ptr<ServerSession> session,
|
||||||
std::unique_ptr<SessionDataBase> data)
|
std::unique_ptr<SessionDataBase> data)
|
||||||
: session(std::move(session)), data(std::move(data)) {}
|
: session(std::move(session)), data(std::move(data)) {}
|
||||||
|
|
||||||
void SessionRequestHandler::ClientConnected(SharedPtr<ServerSession> server_session) {
|
void SessionRequestHandler::ClientConnected(std::shared_ptr<ServerSession> server_session) {
|
||||||
server_session->SetHleHandler(shared_from_this());
|
server_session->SetHleHandler(shared_from_this());
|
||||||
connected_sessions.emplace_back(std::move(server_session), MakeSessionData());
|
connected_sessions.emplace_back(std::move(server_session), MakeSessionData());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SessionRequestHandler::ClientDisconnected(SharedPtr<ServerSession> server_session) {
|
void SessionRequestHandler::ClientDisconnected(std::shared_ptr<ServerSession> server_session) {
|
||||||
server_session->SetHleHandler(nullptr);
|
server_session->SetHleHandler(nullptr);
|
||||||
connected_sessions.erase(
|
connected_sessions.erase(
|
||||||
std::remove_if(connected_sessions.begin(), connected_sessions.end(),
|
std::remove_if(connected_sessions.begin(), connected_sessions.end(),
|
||||||
|
@ -32,14 +32,14 @@ void SessionRequestHandler::ClientDisconnected(SharedPtr<ServerSession> server_s
|
||||||
connected_sessions.end());
|
connected_sessions.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread,
|
std::shared_ptr<Event> HLERequestContext::SleepClientThread(std::shared_ptr<Thread> thread,
|
||||||
const std::string& reason,
|
const std::string& reason,
|
||||||
std::chrono::nanoseconds timeout,
|
std::chrono::nanoseconds timeout,
|
||||||
WakeupCallback&& callback) {
|
WakeupCallback&& callback) {
|
||||||
// Put the client thread to sleep until the wait event is signaled or the timeout expires.
|
// Put the client thread to sleep until the wait event is signaled or the timeout expires.
|
||||||
thread->wakeup_callback = [context = *this, callback](ThreadWakeupReason reason,
|
thread->wakeup_callback = [context = *this,
|
||||||
SharedPtr<Thread> thread,
|
callback](ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||||
SharedPtr<WaitObject> object) mutable {
|
std::shared_ptr<WaitObject> object) mutable {
|
||||||
ASSERT(thread->status == ThreadStatus::WaitHleEvent);
|
ASSERT(thread->status == ThreadStatus::WaitHleEvent);
|
||||||
callback(thread, context, reason);
|
callback(thread, context, reason);
|
||||||
|
|
||||||
|
@ -68,19 +68,19 @@ SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread,
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
HLERequestContext::HLERequestContext(KernelSystem& kernel, SharedPtr<ServerSession> session)
|
HLERequestContext::HLERequestContext(KernelSystem& kernel, std::shared_ptr<ServerSession> session)
|
||||||
: kernel(kernel), session(std::move(session)) {
|
: kernel(kernel), session(std::move(session)) {
|
||||||
cmd_buf[0] = 0;
|
cmd_buf[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
HLERequestContext::~HLERequestContext() = default;
|
HLERequestContext::~HLERequestContext() = default;
|
||||||
|
|
||||||
SharedPtr<Object> HLERequestContext::GetIncomingHandle(u32 id_from_cmdbuf) const {
|
std::shared_ptr<Object> HLERequestContext::GetIncomingHandle(u32 id_from_cmdbuf) const {
|
||||||
ASSERT(id_from_cmdbuf < request_handles.size());
|
ASSERT(id_from_cmdbuf < request_handles.size());
|
||||||
return request_handles[id_from_cmdbuf];
|
return request_handles[id_from_cmdbuf];
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 HLERequestContext::AddOutgoingHandle(SharedPtr<Object> object) {
|
u32 HLERequestContext::AddOutgoingHandle(std::shared_ptr<Object> object) {
|
||||||
request_handles.push_back(std::move(object));
|
request_handles.push_back(std::move(object));
|
||||||
return static_cast<u32>(request_handles.size() - 1);
|
return static_cast<u32>(request_handles.size() - 1);
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* sr
|
||||||
ASSERT(i + num_handles <= command_size); // TODO(yuriks): Return error
|
ASSERT(i + num_handles <= command_size); // TODO(yuriks): Return error
|
||||||
for (u32 j = 0; j < num_handles; ++j) {
|
for (u32 j = 0; j < num_handles; ++j) {
|
||||||
Handle handle = src_cmdbuf[i];
|
Handle handle = src_cmdbuf[i];
|
||||||
SharedPtr<Object> object = nullptr;
|
std::shared_ptr<Object> object = nullptr;
|
||||||
if (handle != 0) {
|
if (handle != 0) {
|
||||||
object = src_process.handle_table.GetGeneric(handle);
|
object = src_process.handle_table.GetGeneric(handle);
|
||||||
ASSERT(object != nullptr); // TODO(yuriks): Return error
|
ASSERT(object != nullptr); // TODO(yuriks): Return error
|
||||||
|
@ -185,7 +185,7 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf,
|
||||||
u32 num_handles = IPC::HandleNumberFromDesc(descriptor);
|
u32 num_handles = IPC::HandleNumberFromDesc(descriptor);
|
||||||
ASSERT(i + num_handles <= command_size);
|
ASSERT(i + num_handles <= command_size);
|
||||||
for (u32 j = 0; j < num_handles; ++j) {
|
for (u32 j = 0; j < num_handles; ++j) {
|
||||||
SharedPtr<Object> object = GetIncomingHandle(cmd_buf[i]);
|
std::shared_ptr<Object> object = GetIncomingHandle(cmd_buf[i]);
|
||||||
Handle handle = 0;
|
Handle handle = 0;
|
||||||
if (object != nullptr) {
|
if (object != nullptr) {
|
||||||
// TODO(yuriks): Figure out the proper error handling for if this fails
|
// TODO(yuriks): Figure out the proper error handling for if this fails
|
||||||
|
|
|
@ -55,14 +55,14 @@ public:
|
||||||
* associated ServerSession alive for the duration of the connection.
|
* associated ServerSession alive for the duration of the connection.
|
||||||
* @param server_session Owning pointer to the ServerSession associated with the connection.
|
* @param server_session Owning pointer to the ServerSession associated with the connection.
|
||||||
*/
|
*/
|
||||||
virtual void ClientConnected(SharedPtr<ServerSession> server_session);
|
virtual void ClientConnected(std::shared_ptr<ServerSession> server_session);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signals that a client has just disconnected from this HLE handler and releases the
|
* Signals that a client has just disconnected from this HLE handler and releases the
|
||||||
* associated ServerSession.
|
* associated ServerSession.
|
||||||
* @param server_session ServerSession associated with the connection.
|
* @param server_session ServerSession associated with the connection.
|
||||||
*/
|
*/
|
||||||
virtual void ClientDisconnected(SharedPtr<ServerSession> server_session);
|
virtual void ClientDisconnected(std::shared_ptr<ServerSession> server_session);
|
||||||
|
|
||||||
/// Empty placeholder structure for services with no per-session data. The session data classes
|
/// Empty placeholder structure for services with no per-session data. The session data classes
|
||||||
/// in each service must inherit from this.
|
/// in each service must inherit from this.
|
||||||
|
@ -76,7 +76,7 @@ protected:
|
||||||
|
|
||||||
/// Returns the session data associated with the server session.
|
/// Returns the session data associated with the server session.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T* GetSessionData(SharedPtr<ServerSession> session) {
|
T* GetSessionData(std::shared_ptr<ServerSession> session) {
|
||||||
static_assert(std::is_base_of<SessionDataBase, T>(),
|
static_assert(std::is_base_of<SessionDataBase, T>(),
|
||||||
"T is not a subclass of SessionDataBase");
|
"T is not a subclass of SessionDataBase");
|
||||||
auto itr = std::find_if(connected_sessions.begin(), connected_sessions.end(),
|
auto itr = std::find_if(connected_sessions.begin(), connected_sessions.end(),
|
||||||
|
@ -86,9 +86,9 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SessionInfo {
|
struct SessionInfo {
|
||||||
SessionInfo(SharedPtr<ServerSession> session, std::unique_ptr<SessionDataBase> data);
|
SessionInfo(std::shared_ptr<ServerSession> session, std::unique_ptr<SessionDataBase> data);
|
||||||
|
|
||||||
SharedPtr<ServerSession> session;
|
std::shared_ptr<ServerSession> session;
|
||||||
std::unique_ptr<SessionDataBase> data;
|
std::unique_ptr<SessionDataBase> data;
|
||||||
};
|
};
|
||||||
/// List of sessions that are connected to this handler. A ServerSession whose server endpoint
|
/// List of sessions that are connected to this handler. A ServerSession whose server endpoint
|
||||||
|
@ -158,7 +158,7 @@ private:
|
||||||
*/
|
*/
|
||||||
class HLERequestContext {
|
class HLERequestContext {
|
||||||
public:
|
public:
|
||||||
HLERequestContext(KernelSystem& kernel, SharedPtr<ServerSession> session);
|
HLERequestContext(KernelSystem& kernel, std::shared_ptr<ServerSession> session);
|
||||||
~HLERequestContext();
|
~HLERequestContext();
|
||||||
|
|
||||||
/// Returns a pointer to the IPC command buffer for this request.
|
/// Returns a pointer to the IPC command buffer for this request.
|
||||||
|
@ -170,12 +170,12 @@ public:
|
||||||
* Returns the session through which this request was made. This can be used as a map key to
|
* Returns the session through which this request was made. This can be used as a map key to
|
||||||
* access per-client data on services.
|
* access per-client data on services.
|
||||||
*/
|
*/
|
||||||
SharedPtr<ServerSession> Session() const {
|
std::shared_ptr<ServerSession> Session() const {
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
using WakeupCallback = std::function<void(SharedPtr<Thread> thread, HLERequestContext& context,
|
using WakeupCallback = std::function<void(
|
||||||
ThreadWakeupReason reason)>;
|
std::shared_ptr<Thread> thread, HLERequestContext& context, ThreadWakeupReason reason)>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Puts the specified guest thread to sleep until the returned event is signaled or until the
|
* Puts the specified guest thread to sleep until the returned event is signaled or until the
|
||||||
|
@ -189,20 +189,22 @@ public:
|
||||||
* was called.
|
* was called.
|
||||||
* @returns Event that when signaled will resume the thread and call the callback function.
|
* @returns Event that when signaled will resume the thread and call the callback function.
|
||||||
*/
|
*/
|
||||||
SharedPtr<Event> SleepClientThread(SharedPtr<Thread> thread, const std::string& reason,
|
std::shared_ptr<Event> SleepClientThread(std::shared_ptr<Thread> thread,
|
||||||
std::chrono::nanoseconds timeout, WakeupCallback&& callback);
|
const std::string& reason,
|
||||||
|
std::chrono::nanoseconds timeout,
|
||||||
|
WakeupCallback&& callback);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves a object id from the request command buffer into a pointer to an object. See the
|
* Resolves a object id from the request command buffer into a pointer to an object. See the
|
||||||
* "HLE handle protocol" section in the class documentation for more details.
|
* "HLE handle protocol" section in the class documentation for more details.
|
||||||
*/
|
*/
|
||||||
SharedPtr<Object> GetIncomingHandle(u32 id_from_cmdbuf) const;
|
std::shared_ptr<Object> GetIncomingHandle(u32 id_from_cmdbuf) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an outgoing object to the response, returning the id which should be used to reference
|
* Adds an outgoing object to the response, returning the id which should be used to reference
|
||||||
* it. See the "HLE handle protocol" section in the class documentation for more details.
|
* it. See the "HLE handle protocol" section in the class documentation for more details.
|
||||||
*/
|
*/
|
||||||
u32 AddOutgoingHandle(SharedPtr<Object> object);
|
u32 AddOutgoingHandle(std::shared_ptr<Object> object);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Discards all Objects from the context, invalidating all ids. This may be called after reading
|
* Discards all Objects from the context, invalidating all ids. This may be called after reading
|
||||||
|
@ -237,9 +239,9 @@ public:
|
||||||
private:
|
private:
|
||||||
KernelSystem& kernel;
|
KernelSystem& kernel;
|
||||||
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf;
|
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf;
|
||||||
SharedPtr<ServerSession> session;
|
std::shared_ptr<ServerSession> session;
|
||||||
// TODO(yuriks): Check common usage of this and optimize size accordingly
|
// TODO(yuriks): Check common usage of this and optimize size accordingly
|
||||||
boost::container::small_vector<SharedPtr<Object>, 8> request_handles;
|
boost::container::small_vector<std::shared_ptr<Object>, 8> request_handles;
|
||||||
// The static buffers will be created when the IPC request is translated.
|
// The static buffers will be created when the IPC request is translated.
|
||||||
std::array<std::vector<u8>, IPC::MAX_STATIC_BUFFERS> static_buffers;
|
std::array<std::vector<u8>, IPC::MAX_STATIC_BUFFERS> static_buffers;
|
||||||
// The mapped buffers will be created when the IPC request is translated
|
// The mapped buffers will be created when the IPC request is translated
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
ResultCode TranslateCommandBuffer(Memory::MemorySystem& memory, SharedPtr<Thread> src_thread,
|
ResultCode TranslateCommandBuffer(Memory::MemorySystem& memory, std::shared_ptr<Thread> src_thread,
|
||||||
SharedPtr<Thread> dst_thread, VAddr src_address,
|
std::shared_ptr<Thread> dst_thread, VAddr src_address,
|
||||||
VAddr dst_address,
|
VAddr dst_address,
|
||||||
std::vector<MappedBufferContext>& mapped_buffer_context,
|
std::vector<MappedBufferContext>& mapped_buffer_context,
|
||||||
bool reply) {
|
bool reply) {
|
||||||
|
@ -55,14 +55,14 @@ ResultCode TranslateCommandBuffer(Memory::MemorySystem& memory, SharedPtr<Thread
|
||||||
|
|
||||||
for (u32 j = 0; j < num_handles; ++j) {
|
for (u32 j = 0; j < num_handles; ++j) {
|
||||||
Handle handle = cmd_buf[i];
|
Handle handle = cmd_buf[i];
|
||||||
SharedPtr<Object> object = nullptr;
|
std::shared_ptr<Object> object = nullptr;
|
||||||
// Perform pseudo-handle detection here because by the time this function is called,
|
// Perform pseudo-handle detection here because by the time this function is called,
|
||||||
// the current thread and process are no longer the ones which created this IPC
|
// the current thread and process are no longer the ones which created this IPC
|
||||||
// request, but the ones that are handling it.
|
// request, but the ones that are handling it.
|
||||||
if (handle == CurrentThread) {
|
if (handle == CurrentThread) {
|
||||||
object = src_thread;
|
object = src_thread;
|
||||||
} else if (handle == CurrentProcess) {
|
} else if (handle == CurrentProcess) {
|
||||||
object = src_process;
|
object = SharedFrom(src_process);
|
||||||
} else if (handle != 0) {
|
} else if (handle != 0) {
|
||||||
object = src_process->handle_table.GetGeneric(handle);
|
object = src_process->handle_table.GetGeneric(handle);
|
||||||
if (descriptor == IPC::DescriptorType::MoveHandle) {
|
if (descriptor == IPC::DescriptorType::MoveHandle) {
|
||||||
|
|
|
@ -27,8 +27,8 @@ struct MappedBufferContext {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Performs IPC command buffer translation from one process to another.
|
/// Performs IPC command buffer translation from one process to another.
|
||||||
ResultCode TranslateCommandBuffer(Memory::MemorySystem& memory, SharedPtr<Thread> src_thread,
|
ResultCode TranslateCommandBuffer(Memory::MemorySystem& memory, std::shared_ptr<Thread> src_thread,
|
||||||
SharedPtr<Thread> dst_thread, VAddr src_address,
|
std::shared_ptr<Thread> dst_thread, VAddr src_address,
|
||||||
VAddr dst_address,
|
VAddr dst_address,
|
||||||
std::vector<MappedBufferContext>& mapped_buffer_context,
|
std::vector<MappedBufferContext>& mapped_buffer_context,
|
||||||
bool reply);
|
bool reply);
|
||||||
|
|
|
@ -42,11 +42,11 @@ u32 KernelSystem::GenerateObjectID() {
|
||||||
return next_object_id++;
|
return next_object_id++;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<Process> KernelSystem::GetCurrentProcess() const {
|
std::shared_ptr<Process> KernelSystem::GetCurrentProcess() const {
|
||||||
return current_process;
|
return current_process;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KernelSystem::SetCurrentProcess(SharedPtr<Process> process) {
|
void KernelSystem::SetCurrentProcess(std::shared_ptr<Process> process) {
|
||||||
current_process = std::move(process);
|
current_process = std::move(process);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ const SharedPage::Handler& KernelSystem::GetSharedPageHandler() const {
|
||||||
return *shared_page_handler;
|
return *shared_page_handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KernelSystem::AddNamedPort(std::string name, SharedPtr<ClientPort> port) {
|
void KernelSystem::AddNamedPort(std::string name, std::shared_ptr<ClientPort> port) {
|
||||||
named_ports.emplace(std::move(name), std::move(port));
|
named_ports.emplace(std::move(name), std::move(port));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,9 +78,6 @@ enum class MemoryRegion : u16 {
|
||||||
BASE = 3,
|
BASE = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
using SharedPtr = boost::intrusive_ptr<T>;
|
|
||||||
|
|
||||||
class KernelSystem {
|
class KernelSystem {
|
||||||
public:
|
public:
|
||||||
explicit KernelSystem(Memory::MemorySystem& memory, Core::Timing& timing,
|
explicit KernelSystem(Memory::MemorySystem& memory, Core::Timing& timing,
|
||||||
|
@ -93,14 +90,14 @@ public:
|
||||||
* @param name Optional name used for debugging.
|
* @param name Optional name used for debugging.
|
||||||
* @returns The created AddressArbiter.
|
* @returns The created AddressArbiter.
|
||||||
*/
|
*/
|
||||||
SharedPtr<AddressArbiter> CreateAddressArbiter(std::string name = "Unknown");
|
std::shared_ptr<AddressArbiter> CreateAddressArbiter(std::string name = "Unknown");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an event
|
* Creates an event
|
||||||
* @param reset_type ResetType describing how to create event
|
* @param reset_type ResetType describing how to create event
|
||||||
* @param name Optional name of event
|
* @param name Optional name of event
|
||||||
*/
|
*/
|
||||||
SharedPtr<Event> CreateEvent(ResetType reset_type, std::string name = "Unknown");
|
std::shared_ptr<Event> CreateEvent(ResetType reset_type, std::string name = "Unknown");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a mutex.
|
* Creates a mutex.
|
||||||
|
@ -108,11 +105,11 @@ public:
|
||||||
* @param name Optional name of mutex
|
* @param name Optional name of mutex
|
||||||
* @return Pointer to new Mutex object
|
* @return Pointer to new Mutex object
|
||||||
*/
|
*/
|
||||||
SharedPtr<Mutex> CreateMutex(bool initial_locked, std::string name = "Unknown");
|
std::shared_ptr<Mutex> CreateMutex(bool initial_locked, std::string name = "Unknown");
|
||||||
|
|
||||||
SharedPtr<CodeSet> CreateCodeSet(std::string name, u64 program_id);
|
std::shared_ptr<CodeSet> CreateCodeSet(std::string name, u64 program_id);
|
||||||
|
|
||||||
SharedPtr<Process> CreateProcess(SharedPtr<CodeSet> code_set);
|
std::shared_ptr<Process> CreateProcess(std::shared_ptr<CodeSet> code_set);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates and returns a new thread. The new thread is immediately scheduled
|
* Creates and returns a new thread. The new thread is immediately scheduled
|
||||||
|
@ -125,9 +122,9 @@ public:
|
||||||
* @param owner_process The parent process for the thread
|
* @param owner_process The parent process for the thread
|
||||||
* @return A shared pointer to the newly created thread
|
* @return A shared pointer to the newly created thread
|
||||||
*/
|
*/
|
||||||
ResultVal<SharedPtr<Thread>> CreateThread(std::string name, VAddr entry_point, u32 priority,
|
ResultVal<std::shared_ptr<Thread>> CreateThread(std::string name, VAddr entry_point,
|
||||||
u32 arg, s32 processor_id, VAddr stack_top,
|
u32 priority, u32 arg, s32 processor_id,
|
||||||
Process& owner_process);
|
VAddr stack_top, Process& owner_process);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a semaphore.
|
* Creates a semaphore.
|
||||||
|
@ -136,7 +133,7 @@ public:
|
||||||
* @param name Optional name of semaphore
|
* @param name Optional name of semaphore
|
||||||
* @return The created semaphore
|
* @return The created semaphore
|
||||||
*/
|
*/
|
||||||
ResultVal<SharedPtr<Semaphore>> CreateSemaphore(s32 initial_count, s32 max_count,
|
ResultVal<std::shared_ptr<Semaphore>> CreateSemaphore(s32 initial_count, s32 max_count,
|
||||||
std::string name = "Unknown");
|
std::string name = "Unknown");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -145,7 +142,7 @@ public:
|
||||||
* @param name Optional name of timer
|
* @param name Optional name of timer
|
||||||
* @return The created Timer
|
* @return The created Timer
|
||||||
*/
|
*/
|
||||||
SharedPtr<Timer> CreateTimer(ResetType reset_type, std::string name = "Unknown");
|
std::shared_ptr<Timer> CreateTimer(ResetType reset_type, std::string name = "Unknown");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a pair of ServerPort and an associated ClientPort.
|
* Creates a pair of ServerPort and an associated ClientPort.
|
||||||
|
@ -154,7 +151,7 @@ public:
|
||||||
* @param name Optional name of the ports
|
* @param name Optional name of the ports
|
||||||
* @return The created port tuple
|
* @return The created port tuple
|
||||||
*/
|
*/
|
||||||
std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> CreatePortPair(
|
std::tuple<std::shared_ptr<ServerPort>, std::shared_ptr<ClientPort>> CreatePortPair(
|
||||||
u32 max_sessions, std::string name = "UnknownPort");
|
u32 max_sessions, std::string name = "UnknownPort");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -163,8 +160,8 @@ public:
|
||||||
* @param client_port Optional The ClientPort that spawned this session.
|
* @param client_port Optional The ClientPort that spawned this session.
|
||||||
* @return The created session tuple
|
* @return The created session tuple
|
||||||
*/
|
*/
|
||||||
std::tuple<SharedPtr<ServerSession>, SharedPtr<ClientSession>> CreateSessionPair(
|
std::tuple<std::shared_ptr<ServerSession>, std::shared_ptr<ClientSession>> CreateSessionPair(
|
||||||
const std::string& name = "Unknown", SharedPtr<ClientPort> client_port = nullptr);
|
const std::string& name = "Unknown", std::shared_ptr<ClientPort> client_port = nullptr);
|
||||||
|
|
||||||
ResourceLimitList& ResourceLimit();
|
ResourceLimitList& ResourceLimit();
|
||||||
const ResourceLimitList& ResourceLimit() const;
|
const ResourceLimitList& ResourceLimit() const;
|
||||||
|
@ -181,12 +178,10 @@ public:
|
||||||
* linear heap.
|
* linear heap.
|
||||||
* @param name Optional object name, used for debugging purposes.
|
* @param name Optional object name, used for debugging purposes.
|
||||||
*/
|
*/
|
||||||
ResultVal<SharedPtr<SharedMemory>> CreateSharedMemory(Process* owner_process, u32 size,
|
ResultVal<std::shared_ptr<SharedMemory>> CreateSharedMemory(
|
||||||
MemoryPermission permissions,
|
Process* owner_process, u32 size, MemoryPermission permissions,
|
||||||
MemoryPermission other_permissions,
|
MemoryPermission other_permissions, VAddr address = 0,
|
||||||
VAddr address = 0,
|
MemoryRegion region = MemoryRegion::BASE, std::string name = "Unknown");
|
||||||
MemoryRegion region = MemoryRegion::BASE,
|
|
||||||
std::string name = "Unknown");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a shared memory object from a block of memory managed by an HLE applet.
|
* Creates a shared memory object from a block of memory managed by an HLE applet.
|
||||||
|
@ -197,7 +192,7 @@ public:
|
||||||
* block.
|
* block.
|
||||||
* @param name Optional object name, used for debugging purposes.
|
* @param name Optional object name, used for debugging purposes.
|
||||||
*/
|
*/
|
||||||
SharedPtr<SharedMemory> CreateSharedMemoryForApplet(u32 offset, u32 size,
|
std::shared_ptr<SharedMemory> CreateSharedMemoryForApplet(u32 offset, u32 size,
|
||||||
MemoryPermission permissions,
|
MemoryPermission permissions,
|
||||||
MemoryPermission other_permissions,
|
MemoryPermission other_permissions,
|
||||||
std::string name = "Unknown Applet");
|
std::string name = "Unknown Applet");
|
||||||
|
@ -205,10 +200,10 @@ public:
|
||||||
u32 GenerateObjectID();
|
u32 GenerateObjectID();
|
||||||
|
|
||||||
/// Retrieves a process from the current list of processes.
|
/// Retrieves a process from the current list of processes.
|
||||||
SharedPtr<Process> GetProcessById(u32 process_id) const;
|
std::shared_ptr<Process> GetProcessById(u32 process_id) const;
|
||||||
|
|
||||||
SharedPtr<Process> GetCurrentProcess() const;
|
std::shared_ptr<Process> GetCurrentProcess() const;
|
||||||
void SetCurrentProcess(SharedPtr<Process> process);
|
void SetCurrentProcess(std::shared_ptr<Process> process);
|
||||||
|
|
||||||
ThreadManager& GetThreadManager();
|
ThreadManager& GetThreadManager();
|
||||||
const ThreadManager& GetThreadManager() const;
|
const ThreadManager& GetThreadManager() const;
|
||||||
|
@ -228,14 +223,14 @@ public:
|
||||||
std::array<MemoryRegionInfo, 3> memory_regions;
|
std::array<MemoryRegionInfo, 3> memory_regions;
|
||||||
|
|
||||||
/// Adds a port to the named port table
|
/// Adds a port to the named port table
|
||||||
void AddNamedPort(std::string name, SharedPtr<ClientPort> port);
|
void AddNamedPort(std::string name, std::shared_ptr<ClientPort> port);
|
||||||
|
|
||||||
void PrepareReschedule() {
|
void PrepareReschedule() {
|
||||||
prepare_reschedule_callback();
|
prepare_reschedule_callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort
|
/// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort
|
||||||
std::unordered_map<std::string, SharedPtr<ClientPort>> named_ports;
|
std::unordered_map<std::string, std::shared_ptr<ClientPort>> named_ports;
|
||||||
|
|
||||||
Memory::MemorySystem& memory;
|
Memory::MemorySystem& memory;
|
||||||
|
|
||||||
|
@ -263,9 +258,9 @@ private:
|
||||||
u32 next_process_id = 10;
|
u32 next_process_id = 10;
|
||||||
|
|
||||||
// Lists all processes that exist in the current session.
|
// Lists all processes that exist in the current session.
|
||||||
std::vector<SharedPtr<Process>> process_list;
|
std::vector<std::shared_ptr<Process>> process_list;
|
||||||
|
|
||||||
SharedPtr<Process> current_process;
|
std::shared_ptr<Process> current_process;
|
||||||
|
|
||||||
std::unique_ptr<ThreadManager> thread_manager;
|
std::unique_ptr<ThreadManager> thread_manager;
|
||||||
|
|
||||||
|
|
|
@ -27,8 +27,8 @@ void ReleaseThreadMutexes(Thread* thread) {
|
||||||
Mutex::Mutex(KernelSystem& kernel) : WaitObject(kernel), kernel(kernel) {}
|
Mutex::Mutex(KernelSystem& kernel) : WaitObject(kernel), kernel(kernel) {}
|
||||||
Mutex::~Mutex() {}
|
Mutex::~Mutex() {}
|
||||||
|
|
||||||
SharedPtr<Mutex> KernelSystem::CreateMutex(bool initial_locked, std::string name) {
|
std::shared_ptr<Mutex> KernelSystem::CreateMutex(bool initial_locked, std::string name) {
|
||||||
SharedPtr<Mutex> mutex(new Mutex(*this));
|
auto mutex{std::make_shared<Mutex>(*this)};
|
||||||
|
|
||||||
mutex->lock_count = 0;
|
mutex->lock_count = 0;
|
||||||
mutex->name = std::move(name);
|
mutex->name = std::move(name);
|
||||||
|
@ -42,7 +42,7 @@ SharedPtr<Mutex> KernelSystem::CreateMutex(bool initial_locked, std::string name
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mutex::ShouldWait(Thread* thread) const {
|
bool Mutex::ShouldWait(Thread* thread) const {
|
||||||
return lock_count > 0 && thread != holding_thread;
|
return lock_count > 0 && thread != holding_thread.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mutex::Acquire(Thread* thread) {
|
void Mutex::Acquire(Thread* thread) {
|
||||||
|
@ -51,8 +51,8 @@ void Mutex::Acquire(Thread* thread) {
|
||||||
// Actually "acquire" the mutex only if we don't already have it
|
// Actually "acquire" the mutex only if we don't already have it
|
||||||
if (lock_count == 0) {
|
if (lock_count == 0) {
|
||||||
priority = thread->current_priority;
|
priority = thread->current_priority;
|
||||||
thread->held_mutexes.insert(this);
|
thread->held_mutexes.insert(SharedFrom(this));
|
||||||
holding_thread = thread;
|
holding_thread = SharedFrom(thread);
|
||||||
thread->UpdatePriority();
|
thread->UpdatePriority();
|
||||||
kernel.PrepareReschedule();
|
kernel.PrepareReschedule();
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ void Mutex::Acquire(Thread* thread) {
|
||||||
|
|
||||||
ResultCode Mutex::Release(Thread* thread) {
|
ResultCode Mutex::Release(Thread* thread) {
|
||||||
// We can only release the mutex if it's held by the calling thread.
|
// We can only release the mutex if it's held by the calling thread.
|
||||||
if (thread != holding_thread) {
|
if (thread != holding_thread.get()) {
|
||||||
if (holding_thread) {
|
if (holding_thread) {
|
||||||
LOG_ERROR(
|
LOG_ERROR(
|
||||||
Kernel,
|
Kernel,
|
||||||
|
@ -83,7 +83,7 @@ ResultCode Mutex::Release(Thread* thread) {
|
||||||
|
|
||||||
// Yield to the next thread only if we've fully released the mutex
|
// Yield to the next thread only if we've fully released the mutex
|
||||||
if (lock_count == 0) {
|
if (lock_count == 0) {
|
||||||
holding_thread->held_mutexes.erase(this);
|
holding_thread->held_mutexes.erase(SharedFrom(this));
|
||||||
holding_thread->UpdatePriority();
|
holding_thread->UpdatePriority();
|
||||||
holding_thread = nullptr;
|
holding_thread = nullptr;
|
||||||
WakeupAllWaitingThreads();
|
WakeupAllWaitingThreads();
|
||||||
|
@ -93,15 +93,15 @@ ResultCode Mutex::Release(Thread* thread) {
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mutex::AddWaitingThread(SharedPtr<Thread> thread) {
|
void Mutex::AddWaitingThread(std::shared_ptr<Thread> thread) {
|
||||||
WaitObject::AddWaitingThread(thread);
|
WaitObject::AddWaitingThread(thread);
|
||||||
thread->pending_mutexes.insert(this);
|
thread->pending_mutexes.insert(SharedFrom(this));
|
||||||
UpdatePriority();
|
UpdatePriority();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mutex::RemoveWaitingThread(Thread* thread) {
|
void Mutex::RemoveWaitingThread(Thread* thread) {
|
||||||
WaitObject::RemoveWaitingThread(thread);
|
WaitObject::RemoveWaitingThread(thread);
|
||||||
thread->pending_mutexes.erase(this);
|
thread->pending_mutexes.erase(SharedFrom(this));
|
||||||
UpdatePriority();
|
UpdatePriority();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,9 @@ class Thread;
|
||||||
|
|
||||||
class Mutex final : public WaitObject {
|
class Mutex final : public WaitObject {
|
||||||
public:
|
public:
|
||||||
|
explicit Mutex(KernelSystem& kernel);
|
||||||
|
~Mutex() override;
|
||||||
|
|
||||||
std::string GetTypeName() const override {
|
std::string GetTypeName() const override {
|
||||||
return "Mutex";
|
return "Mutex";
|
||||||
}
|
}
|
||||||
|
@ -31,7 +34,7 @@ public:
|
||||||
int lock_count; ///< Number of times the mutex has been acquired
|
int lock_count; ///< Number of times the mutex has been acquired
|
||||||
u32 priority; ///< The priority of the mutex, used for priority inheritance.
|
u32 priority; ///< The priority of the mutex, used for priority inheritance.
|
||||||
std::string name; ///< Name of mutex (optional)
|
std::string name; ///< Name of mutex (optional)
|
||||||
SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex
|
std::shared_ptr<Thread> holding_thread; ///< Thread that has acquired the mutex
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Elevate the mutex priority to the best priority
|
* Elevate the mutex priority to the best priority
|
||||||
|
@ -42,7 +45,7 @@ public:
|
||||||
bool ShouldWait(Thread* thread) const override;
|
bool ShouldWait(Thread* thread) const override;
|
||||||
void Acquire(Thread* thread) override;
|
void Acquire(Thread* thread) override;
|
||||||
|
|
||||||
void AddWaitingThread(SharedPtr<Thread> thread) override;
|
void AddWaitingThread(std::shared_ptr<Thread> thread) override;
|
||||||
void RemoveWaitingThread(Thread* thread) override;
|
void RemoveWaitingThread(Thread* thread) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,10 +56,6 @@ public:
|
||||||
ResultCode Release(Thread* thread);
|
ResultCode Release(Thread* thread);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit Mutex(KernelSystem& kernel);
|
|
||||||
~Mutex() override;
|
|
||||||
|
|
||||||
friend class KernelSystem;
|
|
||||||
KernelSystem& kernel;
|
KernelSystem& kernel;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
|
@ -37,7 +38,7 @@ enum {
|
||||||
DEFAULT_STACK_SIZE = 0x4000,
|
DEFAULT_STACK_SIZE = 0x4000,
|
||||||
};
|
};
|
||||||
|
|
||||||
class Object : NonCopyable {
|
class Object : NonCopyable, public std::enable_shared_from_this<Object> {
|
||||||
public:
|
public:
|
||||||
explicit Object(KernelSystem& kernel);
|
explicit Object(KernelSystem& kernel);
|
||||||
virtual ~Object();
|
virtual ~Object();
|
||||||
|
@ -62,22 +63,15 @@ public:
|
||||||
bool IsWaitable() const;
|
bool IsWaitable() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend void intrusive_ptr_add_ref(Object*);
|
|
||||||
friend void intrusive_ptr_release(Object*);
|
|
||||||
|
|
||||||
std::atomic<u32> ref_count{0};
|
|
||||||
std::atomic<u32> object_id;
|
std::atomic<u32> object_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Special functions used by boost::instrusive_ptr to do automatic ref-counting
|
template <typename T>
|
||||||
inline void intrusive_ptr_add_ref(Object* object) {
|
std::shared_ptr<T> SharedFrom(T* raw) {
|
||||||
object->ref_count.fetch_add(1, std::memory_order_relaxed);
|
if (raw == nullptr)
|
||||||
}
|
return nullptr;
|
||||||
|
|
||||||
inline void intrusive_ptr_release(Object* object) {
|
return std::static_pointer_cast<T>(raw->shared_from_this());
|
||||||
if (object->ref_count.fetch_sub(1, std::memory_order_acq_rel) == 1) {
|
|
||||||
delete object;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -85,9 +79,9 @@ inline void intrusive_ptr_release(Object* object) {
|
||||||
* @return Derived pointer to the object, or `nullptr` if `object` isn't of type T.
|
* @return Derived pointer to the object, or `nullptr` if `object` isn't of type T.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline SharedPtr<T> DynamicObjectCast(SharedPtr<Object> object) {
|
inline std::shared_ptr<T> DynamicObjectCast(std::shared_ptr<Object> object) {
|
||||||
if (object != nullptr && object->GetHandleType() == T::HANDLE_TYPE) {
|
if (object != nullptr && object->GetHandleType() == T::HANDLE_TYPE) {
|
||||||
return boost::static_pointer_cast<T>(object);
|
return std::static_pointer_cast<T>(object);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
SharedPtr<CodeSet> KernelSystem::CreateCodeSet(std::string name, u64 program_id) {
|
std::shared_ptr<CodeSet> KernelSystem::CreateCodeSet(std::string name, u64 program_id) {
|
||||||
SharedPtr<CodeSet> codeset(new CodeSet(*this));
|
auto codeset{std::make_shared<CodeSet>(*this)};
|
||||||
|
|
||||||
codeset->name = std::move(name);
|
codeset->name = std::move(name);
|
||||||
codeset->program_id = program_id;
|
codeset->program_id = program_id;
|
||||||
|
@ -29,8 +29,8 @@ SharedPtr<CodeSet> KernelSystem::CreateCodeSet(std::string name, u64 program_id)
|
||||||
CodeSet::CodeSet(KernelSystem& kernel) : Object(kernel) {}
|
CodeSet::CodeSet(KernelSystem& kernel) : Object(kernel) {}
|
||||||
CodeSet::~CodeSet() {}
|
CodeSet::~CodeSet() {}
|
||||||
|
|
||||||
SharedPtr<Process> KernelSystem::CreateProcess(SharedPtr<CodeSet> code_set) {
|
std::shared_ptr<Process> KernelSystem::CreateProcess(std::shared_ptr<CodeSet> code_set) {
|
||||||
SharedPtr<Process> process(new Process(*this));
|
auto process{std::make_shared<Process>(*this)};
|
||||||
|
|
||||||
process->codeset = std::move(code_set);
|
process->codeset = std::move(code_set);
|
||||||
process->flags.raw = 0;
|
process->flags.raw = 0;
|
||||||
|
@ -142,7 +142,7 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) {
|
||||||
status = ProcessStatus::Running;
|
status = ProcessStatus::Running;
|
||||||
|
|
||||||
vm_manager.LogLayout(Log::Level::Debug);
|
vm_manager.LogLayout(Log::Level::Debug);
|
||||||
Kernel::SetupMainThread(kernel, codeset->entrypoint, main_thread_priority, this);
|
Kernel::SetupMainThread(kernel, codeset->entrypoint, main_thread_priority, SharedFrom(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
VAddr Process::GetLinearHeapAreaAddress() const {
|
VAddr Process::GetLinearHeapAreaAddress() const {
|
||||||
|
@ -416,10 +416,10 @@ Kernel::Process::~Process() {
|
||||||
kernel.memory.UnregisterPageTable(&vm_manager.page_table);
|
kernel.memory.UnregisterPageTable(&vm_manager.page_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<Process> KernelSystem::GetProcessById(u32 process_id) const {
|
std::shared_ptr<Process> KernelSystem::GetProcessById(u32 process_id) const {
|
||||||
auto itr = std::find_if(
|
auto itr = std::find_if(
|
||||||
process_list.begin(), process_list.end(),
|
process_list.begin(), process_list.end(),
|
||||||
[&](const SharedPtr<Process>& process) { return process->process_id == process_id; });
|
[&](const std::shared_ptr<Process>& process) { return process->process_id == process_id; });
|
||||||
|
|
||||||
if (itr == process_list.end())
|
if (itr == process_list.end())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -52,6 +52,9 @@ struct MemoryRegionInfo;
|
||||||
|
|
||||||
class CodeSet final : public Object {
|
class CodeSet final : public Object {
|
||||||
public:
|
public:
|
||||||
|
explicit CodeSet(KernelSystem& kernel);
|
||||||
|
~CodeSet() override;
|
||||||
|
|
||||||
struct Segment {
|
struct Segment {
|
||||||
std::size_t offset = 0;
|
std::size_t offset = 0;
|
||||||
VAddr addr = 0;
|
VAddr addr = 0;
|
||||||
|
@ -103,16 +106,13 @@ public:
|
||||||
std::string name;
|
std::string name;
|
||||||
/// Title ID corresponding to the process
|
/// Title ID corresponding to the process
|
||||||
u64 program_id;
|
u64 program_id;
|
||||||
|
|
||||||
private:
|
|
||||||
explicit CodeSet(KernelSystem& kernel);
|
|
||||||
~CodeSet() override;
|
|
||||||
|
|
||||||
friend class KernelSystem;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Process final : public Object {
|
class Process final : public Object {
|
||||||
public:
|
public:
|
||||||
|
explicit Process(Kernel::KernelSystem& kernel);
|
||||||
|
~Process() override;
|
||||||
|
|
||||||
std::string GetTypeName() const override {
|
std::string GetTypeName() const override {
|
||||||
return "Process";
|
return "Process";
|
||||||
}
|
}
|
||||||
|
@ -127,9 +127,9 @@ public:
|
||||||
|
|
||||||
HandleTable handle_table;
|
HandleTable handle_table;
|
||||||
|
|
||||||
SharedPtr<CodeSet> codeset;
|
std::shared_ptr<CodeSet> codeset;
|
||||||
/// Resource limit descriptor for this process
|
/// Resource limit descriptor for this process
|
||||||
SharedPtr<ResourceLimit> resource_limit;
|
std::shared_ptr<ResourceLimit> resource_limit;
|
||||||
|
|
||||||
/// The process may only call SVCs which have the corresponding bit set.
|
/// The process may only call SVCs which have the corresponding bit set.
|
||||||
std::bitset<0x80> svc_access_mask;
|
std::bitset<0x80> svc_access_mask;
|
||||||
|
@ -194,10 +194,6 @@ public:
|
||||||
bool privileged = false);
|
bool privileged = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit Process(Kernel::KernelSystem& kernel);
|
|
||||||
~Process() override;
|
|
||||||
|
|
||||||
friend class KernelSystem;
|
|
||||||
KernelSystem& kernel;
|
KernelSystem& kernel;
|
||||||
};
|
};
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
|
|
@ -12,14 +12,14 @@ namespace Kernel {
|
||||||
ResourceLimit::ResourceLimit(KernelSystem& kernel) : Object(kernel) {}
|
ResourceLimit::ResourceLimit(KernelSystem& kernel) : Object(kernel) {}
|
||||||
ResourceLimit::~ResourceLimit() {}
|
ResourceLimit::~ResourceLimit() {}
|
||||||
|
|
||||||
SharedPtr<ResourceLimit> ResourceLimit::Create(KernelSystem& kernel, std::string name) {
|
std::shared_ptr<ResourceLimit> ResourceLimit::Create(KernelSystem& kernel, std::string name) {
|
||||||
SharedPtr<ResourceLimit> resource_limit(new ResourceLimit(kernel));
|
auto resource_limit{std::make_shared<ResourceLimit>(kernel)};
|
||||||
|
|
||||||
resource_limit->name = std::move(name);
|
resource_limit->name = std::move(name);
|
||||||
return resource_limit;
|
return resource_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<ResourceLimit> ResourceLimitList::GetForCategory(ResourceLimitCategory category) {
|
std::shared_ptr<ResourceLimit> ResourceLimitList::GetForCategory(ResourceLimitCategory category) {
|
||||||
switch (category) {
|
switch (category) {
|
||||||
case ResourceLimitCategory::APPLICATION:
|
case ResourceLimitCategory::APPLICATION:
|
||||||
case ResourceLimitCategory::SYS_APPLET:
|
case ResourceLimitCategory::SYS_APPLET:
|
||||||
|
@ -91,7 +91,7 @@ u32 ResourceLimit::GetMaxResourceValue(u32 resource) const {
|
||||||
ResourceLimitList::ResourceLimitList(KernelSystem& kernel) {
|
ResourceLimitList::ResourceLimitList(KernelSystem& kernel) {
|
||||||
// Create the four resource limits that the system uses
|
// Create the four resource limits that the system uses
|
||||||
// Create the APPLICATION resource limit
|
// Create the APPLICATION resource limit
|
||||||
SharedPtr<ResourceLimit> resource_limit = ResourceLimit::Create(kernel, "Applications");
|
std::shared_ptr<ResourceLimit> resource_limit = ResourceLimit::Create(kernel, "Applications");
|
||||||
resource_limit->max_priority = 0x18;
|
resource_limit->max_priority = 0x18;
|
||||||
resource_limit->max_commit = 0x4000000;
|
resource_limit->max_commit = 0x4000000;
|
||||||
resource_limit->max_threads = 0x20;
|
resource_limit->max_threads = 0x20;
|
||||||
|
|
|
@ -32,10 +32,14 @@ enum ResourceTypes {
|
||||||
|
|
||||||
class ResourceLimit final : public Object {
|
class ResourceLimit final : public Object {
|
||||||
public:
|
public:
|
||||||
|
explicit ResourceLimit(KernelSystem& kernel);
|
||||||
|
~ResourceLimit() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a resource limit object.
|
* Creates a resource limit object.
|
||||||
*/
|
*/
|
||||||
static SharedPtr<ResourceLimit> Create(KernelSystem& kernel, std::string name = "Unknown");
|
static std::shared_ptr<ResourceLimit> Create(KernelSystem& kernel,
|
||||||
|
std::string name = "Unknown");
|
||||||
|
|
||||||
std::string GetTypeName() const override {
|
std::string GetTypeName() const override {
|
||||||
return "ResourceLimit";
|
return "ResourceLimit";
|
||||||
|
@ -105,10 +109,6 @@ public:
|
||||||
|
|
||||||
/// Current CPU time that the processes in this category are utilizing
|
/// Current CPU time that the processes in this category are utilizing
|
||||||
s32 current_cpu_time = 0;
|
s32 current_cpu_time = 0;
|
||||||
|
|
||||||
private:
|
|
||||||
explicit ResourceLimit(KernelSystem& kernel);
|
|
||||||
~ResourceLimit() override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResourceLimitList {
|
class ResourceLimitList {
|
||||||
|
@ -121,10 +121,10 @@ public:
|
||||||
* @param category The resource limit category
|
* @param category The resource limit category
|
||||||
* @returns The resource limit associated with the category
|
* @returns The resource limit associated with the category
|
||||||
*/
|
*/
|
||||||
SharedPtr<ResourceLimit> GetForCategory(ResourceLimitCategory category);
|
std::shared_ptr<ResourceLimit> GetForCategory(ResourceLimitCategory category);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::array<SharedPtr<ResourceLimit>, 4> resource_limits;
|
std::array<std::shared_ptr<ResourceLimit>, 4> resource_limits;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
|
|
@ -13,13 +13,14 @@ namespace Kernel {
|
||||||
Semaphore::Semaphore(KernelSystem& kernel) : WaitObject(kernel) {}
|
Semaphore::Semaphore(KernelSystem& kernel) : WaitObject(kernel) {}
|
||||||
Semaphore::~Semaphore() {}
|
Semaphore::~Semaphore() {}
|
||||||
|
|
||||||
ResultVal<SharedPtr<Semaphore>> KernelSystem::CreateSemaphore(s32 initial_count, s32 max_count,
|
ResultVal<std::shared_ptr<Semaphore>> KernelSystem::CreateSemaphore(s32 initial_count,
|
||||||
|
s32 max_count,
|
||||||
std::string name) {
|
std::string name) {
|
||||||
|
|
||||||
if (initial_count > max_count)
|
if (initial_count > max_count)
|
||||||
return ERR_INVALID_COMBINATION_KERNEL;
|
return ERR_INVALID_COMBINATION_KERNEL;
|
||||||
|
|
||||||
SharedPtr<Semaphore> semaphore(new Semaphore(*this));
|
auto semaphore{std::make_shared<Semaphore>(*this)};
|
||||||
|
|
||||||
// When the semaphore is created, some slots are reserved for other threads,
|
// When the semaphore is created, some slots are reserved for other threads,
|
||||||
// and the rest is reserved for the caller thread
|
// and the rest is reserved for the caller thread
|
||||||
|
@ -27,7 +28,7 @@ ResultVal<SharedPtr<Semaphore>> KernelSystem::CreateSemaphore(s32 initial_count,
|
||||||
semaphore->available_count = initial_count;
|
semaphore->available_count = initial_count;
|
||||||
semaphore->name = std::move(name);
|
semaphore->name = std::move(name);
|
||||||
|
|
||||||
return MakeResult<SharedPtr<Semaphore>>(std::move(semaphore));
|
return MakeResult<std::shared_ptr<Semaphore>>(std::move(semaphore));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Semaphore::ShouldWait(Thread* thread) const {
|
bool Semaphore::ShouldWait(Thread* thread) const {
|
||||||
|
|
|
@ -15,6 +15,9 @@ namespace Kernel {
|
||||||
|
|
||||||
class Semaphore final : public WaitObject {
|
class Semaphore final : public WaitObject {
|
||||||
public:
|
public:
|
||||||
|
explicit Semaphore(KernelSystem& kernel);
|
||||||
|
~Semaphore() override;
|
||||||
|
|
||||||
std::string GetTypeName() const override {
|
std::string GetTypeName() const override {
|
||||||
return "Semaphore";
|
return "Semaphore";
|
||||||
}
|
}
|
||||||
|
@ -40,12 +43,6 @@ public:
|
||||||
* @return The number of free slots the semaphore had before this call
|
* @return The number of free slots the semaphore had before this call
|
||||||
*/
|
*/
|
||||||
ResultVal<s32> Release(s32 release_count);
|
ResultVal<s32> Release(s32 release_count);
|
||||||
|
|
||||||
private:
|
|
||||||
explicit Semaphore(KernelSystem& kernel);
|
|
||||||
~Semaphore() override;
|
|
||||||
|
|
||||||
friend class KernelSystem;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace Kernel {
|
||||||
ServerPort::ServerPort(KernelSystem& kernel) : WaitObject(kernel) {}
|
ServerPort::ServerPort(KernelSystem& kernel) : WaitObject(kernel) {}
|
||||||
ServerPort::~ServerPort() {}
|
ServerPort::~ServerPort() {}
|
||||||
|
|
||||||
ResultVal<SharedPtr<ServerSession>> ServerPort::Accept() {
|
ResultVal<std::shared_ptr<ServerSession>> ServerPort::Accept() {
|
||||||
if (pending_sessions.empty()) {
|
if (pending_sessions.empty()) {
|
||||||
return ERR_NO_PENDING_SESSIONS;
|
return ERR_NO_PENDING_SESSIONS;
|
||||||
}
|
}
|
||||||
|
@ -35,11 +35,11 @@ void ServerPort::Acquire(Thread* thread) {
|
||||||
ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
|
ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> KernelSystem::CreatePortPair(
|
std::tuple<std::shared_ptr<ServerPort>, std::shared_ptr<ClientPort>> KernelSystem::CreatePortPair(
|
||||||
u32 max_sessions, std::string name) {
|
u32 max_sessions, std::string name) {
|
||||||
|
|
||||||
SharedPtr<ServerPort> server_port(new ServerPort(*this));
|
auto server_port{std::make_shared<ServerPort>(*this)};
|
||||||
SharedPtr<ClientPort> client_port(new ClientPort(*this));
|
auto client_port{std::make_shared<ClientPort>(*this)};
|
||||||
|
|
||||||
server_port->name = name + "_Server";
|
server_port->name = name + "_Server";
|
||||||
client_port->name = name + "_Client";
|
client_port->name = name + "_Client";
|
||||||
|
|
|
@ -20,6 +20,9 @@ class SessionRequestHandler;
|
||||||
|
|
||||||
class ServerPort final : public WaitObject {
|
class ServerPort final : public WaitObject {
|
||||||
public:
|
public:
|
||||||
|
explicit ServerPort(KernelSystem& kernel);
|
||||||
|
~ServerPort() override;
|
||||||
|
|
||||||
std::string GetTypeName() const override {
|
std::string GetTypeName() const override {
|
||||||
return "ServerPort";
|
return "ServerPort";
|
||||||
}
|
}
|
||||||
|
@ -36,7 +39,7 @@ public:
|
||||||
* Accepts a pending incoming connection on this port. If there are no pending sessions, will
|
* Accepts a pending incoming connection on this port. If there are no pending sessions, will
|
||||||
* return ERR_NO_PENDING_SESSIONS.
|
* return ERR_NO_PENDING_SESSIONS.
|
||||||
*/
|
*/
|
||||||
ResultVal<SharedPtr<ServerSession>> Accept();
|
ResultVal<std::shared_ptr<ServerSession>> Accept();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the HLE handler template for the port. ServerSessions crated by connecting to this port
|
* Sets the HLE handler template for the port. ServerSessions crated by connecting to this port
|
||||||
|
@ -49,7 +52,7 @@ public:
|
||||||
std::string name; ///< Name of port (optional)
|
std::string name; ///< Name of port (optional)
|
||||||
|
|
||||||
/// ServerSessions waiting to be accepted by the port
|
/// ServerSessions waiting to be accepted by the port
|
||||||
std::vector<SharedPtr<ServerSession>> pending_sessions;
|
std::vector<std::shared_ptr<ServerSession>> pending_sessions;
|
||||||
|
|
||||||
/// This session's HLE request handler template (optional)
|
/// This session's HLE request handler template (optional)
|
||||||
/// ServerSessions created from this port inherit a reference to this handler.
|
/// ServerSessions created from this port inherit a reference to this handler.
|
||||||
|
@ -57,12 +60,6 @@ public:
|
||||||
|
|
||||||
bool ShouldWait(Thread* thread) const override;
|
bool ShouldWait(Thread* thread) const override;
|
||||||
void Acquire(Thread* thread) override;
|
void Acquire(Thread* thread) override;
|
||||||
|
|
||||||
private:
|
|
||||||
explicit ServerPort(KernelSystem& kernel);
|
|
||||||
~ServerPort() override;
|
|
||||||
|
|
||||||
friend class KernelSystem;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
|
|
@ -28,8 +28,9 @@ ServerSession::~ServerSession() {
|
||||||
parent->server = nullptr;
|
parent->server = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultVal<SharedPtr<ServerSession>> ServerSession::Create(KernelSystem& kernel, std::string name) {
|
ResultVal<std::shared_ptr<ServerSession>> ServerSession::Create(KernelSystem& kernel,
|
||||||
SharedPtr<ServerSession> server_session(new ServerSession(kernel));
|
std::string name) {
|
||||||
|
auto server_session{std::make_shared<ServerSession>(kernel)};
|
||||||
|
|
||||||
server_session->name = std::move(name);
|
server_session->name = std::move(name);
|
||||||
server_session->parent = nullptr;
|
server_session->parent = nullptr;
|
||||||
|
@ -59,7 +60,7 @@ void ServerSession::Acquire(Thread* thread) {
|
||||||
pending_requesting_threads.pop_back();
|
pending_requesting_threads.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) {
|
ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread) {
|
||||||
// The ServerSession received a sync request, this means that there's new data available
|
// The ServerSession received a sync request, this means that there's new data available
|
||||||
// from its ClientSession, so wake up any threads that may be waiting on a svcReplyAndReceive or
|
// from its ClientSession, so wake up any threads that may be waiting on a svcReplyAndReceive or
|
||||||
// similar.
|
// similar.
|
||||||
|
@ -71,7 +72,7 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) {
|
||||||
kernel.memory.ReadBlock(*current_process, thread->GetCommandBufferAddress(), cmd_buf.data(),
|
kernel.memory.ReadBlock(*current_process, thread->GetCommandBufferAddress(), cmd_buf.data(),
|
||||||
cmd_buf.size() * sizeof(u32));
|
cmd_buf.size() * sizeof(u32));
|
||||||
|
|
||||||
Kernel::HLERequestContext context(kernel, this);
|
Kernel::HLERequestContext context(kernel, SharedFrom(this));
|
||||||
context.PopulateFromIncomingCommandBuffer(cmd_buf.data(), *current_process);
|
context.PopulateFromIncomingCommandBuffer(cmd_buf.data(), *current_process);
|
||||||
|
|
||||||
hle_handler->HandleSyncRequest(context);
|
hle_handler->HandleSyncRequest(context);
|
||||||
|
@ -119,10 +120,10 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) {
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<SharedPtr<ServerSession>, SharedPtr<ClientSession>> KernelSystem::CreateSessionPair(
|
std::tuple<std::shared_ptr<ServerSession>, std::shared_ptr<ClientSession>>
|
||||||
const std::string& name, SharedPtr<ClientPort> port) {
|
KernelSystem::CreateSessionPair(const std::string& name, std::shared_ptr<ClientPort> port) {
|
||||||
auto server_session = ServerSession::Create(*this, name + "_Server").Unwrap();
|
auto server_session = ServerSession::Create(*this, name + "_Server").Unwrap();
|
||||||
SharedPtr<ClientSession> client_session(new ClientSession(*this));
|
auto client_session{std::make_shared<ClientSession>(*this)};
|
||||||
client_session->name = name + "_Client";
|
client_session->name = name + "_Client";
|
||||||
|
|
||||||
std::shared_ptr<Session> parent(new Session);
|
std::shared_ptr<Session> parent(new Session);
|
||||||
|
|
|
@ -37,6 +37,9 @@ class Thread;
|
||||||
*/
|
*/
|
||||||
class ServerSession final : public WaitObject {
|
class ServerSession final : public WaitObject {
|
||||||
public:
|
public:
|
||||||
|
~ServerSession() override;
|
||||||
|
explicit ServerSession(KernelSystem& kernel);
|
||||||
|
|
||||||
std::string GetName() const override {
|
std::string GetName() const override {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
@ -63,7 +66,7 @@ public:
|
||||||
* @param thread Thread that initiated the request.
|
* @param thread Thread that initiated the request.
|
||||||
* @returns ResultCode from the operation.
|
* @returns ResultCode from the operation.
|
||||||
*/
|
*/
|
||||||
ResultCode HandleSyncRequest(SharedPtr<Thread> thread);
|
ResultCode HandleSyncRequest(std::shared_ptr<Thread> thread);
|
||||||
|
|
||||||
bool ShouldWait(Thread* thread) const override;
|
bool ShouldWait(Thread* thread) const override;
|
||||||
|
|
||||||
|
@ -77,20 +80,17 @@ public:
|
||||||
/// List of threads that are pending a response after a sync request. This list is processed in
|
/// List of threads that are pending a response after a sync request. This list is processed in
|
||||||
/// a LIFO manner, thus, the last request will be dispatched first.
|
/// a LIFO manner, thus, the last request will be dispatched first.
|
||||||
/// TODO(Subv): Verify if this is indeed processed in LIFO using a hardware test.
|
/// TODO(Subv): Verify if this is indeed processed in LIFO using a hardware test.
|
||||||
std::vector<SharedPtr<Thread>> pending_requesting_threads;
|
std::vector<std::shared_ptr<Thread>> pending_requesting_threads;
|
||||||
|
|
||||||
/// Thread whose request is currently being handled. A request is considered "handled" when a
|
/// Thread whose request is currently being handled. A request is considered "handled" when a
|
||||||
/// response is sent via svcReplyAndReceive.
|
/// response is sent via svcReplyAndReceive.
|
||||||
/// TODO(Subv): Find a better name for this.
|
/// TODO(Subv): Find a better name for this.
|
||||||
SharedPtr<Thread> currently_handling;
|
std::shared_ptr<Thread> currently_handling;
|
||||||
|
|
||||||
/// A temporary list holding mapped buffer info from IPC request, used for during IPC reply
|
/// A temporary list holding mapped buffer info from IPC request, used for during IPC reply
|
||||||
std::vector<MappedBufferContext> mapped_buffer_context;
|
std::vector<MappedBufferContext> mapped_buffer_context;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit ServerSession(KernelSystem& kernel);
|
|
||||||
~ServerSession() override;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a server session. The server session can have an optional HLE handler,
|
* Creates a server session. The server session can have an optional HLE handler,
|
||||||
* which will be invoked to handle the IPC requests that this session receives.
|
* which will be invoked to handle the IPC requests that this session receives.
|
||||||
|
@ -98,7 +98,7 @@ private:
|
||||||
* @param name Optional name of the server session.
|
* @param name Optional name of the server session.
|
||||||
* @return The created server session
|
* @return The created server session
|
||||||
*/
|
*/
|
||||||
static ResultVal<SharedPtr<ServerSession>> Create(KernelSystem& kernel,
|
static ResultVal<std::shared_ptr<ServerSession>> Create(KernelSystem& kernel,
|
||||||
std::string name = "Unknown");
|
std::string name = "Unknown");
|
||||||
|
|
||||||
friend class KernelSystem;
|
friend class KernelSystem;
|
||||||
|
|
|
@ -22,6 +22,6 @@ class Session final {
|
||||||
public:
|
public:
|
||||||
ClientSession* client = nullptr; ///< The client endpoint of the session.
|
ClientSession* client = nullptr; ///< The client endpoint of the session.
|
||||||
ServerSession* server = nullptr; ///< The server endpoint of the session.
|
ServerSession* server = nullptr; ///< The server endpoint of the session.
|
||||||
SharedPtr<ClientPort> port; ///< The port that this session is associated with (optional).
|
std::shared_ptr<ClientPort> port; ///< The port that this session is associated with (optional).
|
||||||
};
|
};
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
|
|
@ -24,10 +24,10 @@ SharedMemory::~SharedMemory() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultVal<SharedPtr<SharedMemory>> KernelSystem::CreateSharedMemory(
|
ResultVal<std::shared_ptr<SharedMemory>> KernelSystem::CreateSharedMemory(
|
||||||
Process* owner_process, u32 size, MemoryPermission permissions,
|
Process* owner_process, u32 size, MemoryPermission permissions,
|
||||||
MemoryPermission other_permissions, VAddr address, MemoryRegion region, std::string name) {
|
MemoryPermission other_permissions, VAddr address, MemoryRegion region, std::string name) {
|
||||||
SharedPtr<SharedMemory> shared_memory(new SharedMemory(*this));
|
auto shared_memory{std::make_shared<SharedMemory>(*this)};
|
||||||
|
|
||||||
shared_memory->owner_process = owner_process;
|
shared_memory->owner_process = owner_process;
|
||||||
shared_memory->name = std::move(name);
|
shared_memory->name = std::move(name);
|
||||||
|
@ -69,10 +69,10 @@ ResultVal<SharedPtr<SharedMemory>> KernelSystem::CreateSharedMemory(
|
||||||
return MakeResult(shared_memory);
|
return MakeResult(shared_memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<SharedMemory> KernelSystem::CreateSharedMemoryForApplet(
|
std::shared_ptr<SharedMemory> KernelSystem::CreateSharedMemoryForApplet(
|
||||||
u32 offset, u32 size, MemoryPermission permissions, MemoryPermission other_permissions,
|
u32 offset, u32 size, MemoryPermission permissions, MemoryPermission other_permissions,
|
||||||
std::string name) {
|
std::string name) {
|
||||||
SharedPtr<SharedMemory> shared_memory(new SharedMemory(*this));
|
auto shared_memory{std::make_shared<SharedMemory>(*this)};
|
||||||
|
|
||||||
// Allocate memory in heap
|
// Allocate memory in heap
|
||||||
MemoryRegionInfo* memory_region = GetMemoryRegion(MemoryRegion::SYSTEM);
|
MemoryRegionInfo* memory_region = GetMemoryRegion(MemoryRegion::SYSTEM);
|
||||||
|
|
|
@ -15,6 +15,9 @@ namespace Kernel {
|
||||||
|
|
||||||
class SharedMemory final : public Object {
|
class SharedMemory final : public Object {
|
||||||
public:
|
public:
|
||||||
|
explicit SharedMemory(KernelSystem& kernel);
|
||||||
|
~SharedMemory() override;
|
||||||
|
|
||||||
std::string GetTypeName() const override {
|
std::string GetTypeName() const override {
|
||||||
return "SharedMemory";
|
return "SharedMemory";
|
||||||
}
|
}
|
||||||
|
@ -79,9 +82,6 @@ public:
|
||||||
const u8* GetPointer(u32 offset = 0) const;
|
const u8* GetPointer(u32 offset = 0) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit SharedMemory(KernelSystem& kernel);
|
|
||||||
~SharedMemory() override;
|
|
||||||
|
|
||||||
/// Offset in FCRAM of the shared memory block in the linear heap if no address was specified
|
/// Offset in FCRAM of the shared memory block in the linear heap if no address was specified
|
||||||
/// during creation.
|
/// during creation.
|
||||||
PAddr linear_heap_phys_offset = 0;
|
PAddr linear_heap_phys_offset = 0;
|
||||||
|
|
|
@ -271,7 +271,7 @@ ResultCode SVC::ControlMemory(u32* out_addr, u32 addr0, u32 addr1, u32 size, u32
|
||||||
}
|
}
|
||||||
|
|
||||||
void SVC::ExitProcess() {
|
void SVC::ExitProcess() {
|
||||||
SharedPtr<Process> current_process = kernel.GetCurrentProcess();
|
std::shared_ptr<Process> current_process = kernel.GetCurrentProcess();
|
||||||
LOG_INFO(Kernel_SVC, "Process {} exiting", current_process->process_id);
|
LOG_INFO(Kernel_SVC, "Process {} exiting", current_process->process_id);
|
||||||
|
|
||||||
ASSERT_MSG(current_process->status == ProcessStatus::Running, "Process has already exited");
|
ASSERT_MSG(current_process->status == ProcessStatus::Running, "Process has already exited");
|
||||||
|
@ -281,10 +281,10 @@ void SVC::ExitProcess() {
|
||||||
// Stop all the process threads that are currently waiting for objects.
|
// Stop all the process threads that are currently waiting for objects.
|
||||||
auto& thread_list = kernel.GetThreadManager().GetThreadList();
|
auto& thread_list = kernel.GetThreadManager().GetThreadList();
|
||||||
for (auto& thread : thread_list) {
|
for (auto& thread : thread_list) {
|
||||||
if (thread->owner_process != current_process)
|
if (thread->owner_process != current_process.get())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (thread == kernel.GetThreadManager().GetCurrentThread())
|
if (thread.get() == kernel.GetThreadManager().GetCurrentThread())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// TODO(Subv): When are the other running/ready threads terminated?
|
// TODO(Subv): When are the other running/ready threads terminated?
|
||||||
|
@ -308,7 +308,7 @@ ResultCode SVC::MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 oth
|
||||||
"otherpermission={}",
|
"otherpermission={}",
|
||||||
handle, addr, permissions, other_permissions);
|
handle, addr, permissions, other_permissions);
|
||||||
|
|
||||||
SharedPtr<SharedMemory> shared_memory =
|
std::shared_ptr<SharedMemory> shared_memory =
|
||||||
kernel.GetCurrentProcess()->handle_table.Get<SharedMemory>(handle);
|
kernel.GetCurrentProcess()->handle_table.Get<SharedMemory>(handle);
|
||||||
if (shared_memory == nullptr)
|
if (shared_memory == nullptr)
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
@ -337,8 +337,9 @@ ResultCode SVC::UnmapMemoryBlock(Handle handle, u32 addr) {
|
||||||
|
|
||||||
// TODO(Subv): Return E0A01BF5 if the address is not in the application's heap
|
// TODO(Subv): Return E0A01BF5 if the address is not in the application's heap
|
||||||
|
|
||||||
SharedPtr<Process> current_process = kernel.GetCurrentProcess();
|
std::shared_ptr<Process> current_process = kernel.GetCurrentProcess();
|
||||||
SharedPtr<SharedMemory> shared_memory = current_process->handle_table.Get<SharedMemory>(handle);
|
std::shared_ptr<SharedMemory> shared_memory =
|
||||||
|
current_process->handle_table.Get<SharedMemory>(handle);
|
||||||
if (shared_memory == nullptr)
|
if (shared_memory == nullptr)
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
|
||||||
|
@ -366,7 +367,7 @@ ResultCode SVC::ConnectToPort(Handle* out_handle, VAddr port_name_address) {
|
||||||
|
|
||||||
auto client_port = it->second;
|
auto client_port = it->second;
|
||||||
|
|
||||||
SharedPtr<ClientSession> client_session;
|
std::shared_ptr<ClientSession> client_session;
|
||||||
CASCADE_RESULT(client_session, client_port->Connect());
|
CASCADE_RESULT(client_session, client_port->Connect());
|
||||||
|
|
||||||
// Return the client session
|
// Return the client session
|
||||||
|
@ -376,7 +377,7 @@ ResultCode SVC::ConnectToPort(Handle* out_handle, VAddr port_name_address) {
|
||||||
|
|
||||||
/// Makes a blocking IPC call to an OS service.
|
/// Makes a blocking IPC call to an OS service.
|
||||||
ResultCode SVC::SendSyncRequest(Handle handle) {
|
ResultCode SVC::SendSyncRequest(Handle handle) {
|
||||||
SharedPtr<ClientSession> session =
|
std::shared_ptr<ClientSession> session =
|
||||||
kernel.GetCurrentProcess()->handle_table.Get<ClientSession>(handle);
|
kernel.GetCurrentProcess()->handle_table.Get<ClientSession>(handle);
|
||||||
if (session == nullptr) {
|
if (session == nullptr) {
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
@ -386,7 +387,7 @@ ResultCode SVC::SendSyncRequest(Handle handle) {
|
||||||
|
|
||||||
system.PrepareReschedule();
|
system.PrepareReschedule();
|
||||||
|
|
||||||
return session->SendSyncRequest(kernel.GetThreadManager().GetCurrentThread());
|
return session->SendSyncRequest(SharedFrom(kernel.GetThreadManager().GetCurrentThread()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Close a handle
|
/// Close a handle
|
||||||
|
@ -412,14 +413,14 @@ ResultCode SVC::WaitSynchronization1(Handle handle, s64 nano_seconds) {
|
||||||
return RESULT_TIMEOUT;
|
return RESULT_TIMEOUT;
|
||||||
|
|
||||||
thread->wait_objects = {object};
|
thread->wait_objects = {object};
|
||||||
object->AddWaitingThread(thread);
|
object->AddWaitingThread(SharedFrom(thread));
|
||||||
thread->status = ThreadStatus::WaitSynchAny;
|
thread->status = ThreadStatus::WaitSynchAny;
|
||||||
|
|
||||||
// Create an event to wake the thread up after the specified nanosecond delay has passed
|
// Create an event to wake the thread up after the specified nanosecond delay has passed
|
||||||
thread->WakeAfterDelay(nano_seconds);
|
thread->WakeAfterDelay(nano_seconds);
|
||||||
|
|
||||||
thread->wakeup_callback = [](ThreadWakeupReason reason, SharedPtr<Thread> thread,
|
thread->wakeup_callback = [](ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||||
SharedPtr<WaitObject> object) {
|
std::shared_ptr<WaitObject> object) {
|
||||||
ASSERT(thread->status == ThreadStatus::WaitSynchAny);
|
ASSERT(thread->status == ThreadStatus::WaitSynchAny);
|
||||||
|
|
||||||
if (reason == ThreadWakeupReason::Timeout) {
|
if (reason == ThreadWakeupReason::Timeout) {
|
||||||
|
@ -463,7 +464,7 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle
|
||||||
if (handle_count < 0)
|
if (handle_count < 0)
|
||||||
return ERR_OUT_OF_RANGE;
|
return ERR_OUT_OF_RANGE;
|
||||||
|
|
||||||
using ObjectPtr = SharedPtr<WaitObject>;
|
using ObjectPtr = std::shared_ptr<WaitObject>;
|
||||||
std::vector<ObjectPtr> objects(handle_count);
|
std::vector<ObjectPtr> objects(handle_count);
|
||||||
|
|
||||||
for (int i = 0; i < handle_count; ++i) {
|
for (int i = 0; i < handle_count; ++i) {
|
||||||
|
@ -499,7 +500,7 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle
|
||||||
|
|
||||||
// Add the thread to each of the objects' waiting threads.
|
// Add the thread to each of the objects' waiting threads.
|
||||||
for (auto& object : objects) {
|
for (auto& object : objects) {
|
||||||
object->AddWaitingThread(thread);
|
object->AddWaitingThread(SharedFrom(thread));
|
||||||
}
|
}
|
||||||
|
|
||||||
thread->wait_objects = std::move(objects);
|
thread->wait_objects = std::move(objects);
|
||||||
|
@ -507,8 +508,8 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle
|
||||||
// Create an event to wake the thread up after the specified nanosecond delay has passed
|
// Create an event to wake the thread up after the specified nanosecond delay has passed
|
||||||
thread->WakeAfterDelay(nano_seconds);
|
thread->WakeAfterDelay(nano_seconds);
|
||||||
|
|
||||||
thread->wakeup_callback = [](ThreadWakeupReason reason, SharedPtr<Thread> thread,
|
thread->wakeup_callback = [](ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||||
SharedPtr<WaitObject> object) {
|
std::shared_ptr<WaitObject> object) {
|
||||||
ASSERT(thread->status == ThreadStatus::WaitSynchAll);
|
ASSERT(thread->status == ThreadStatus::WaitSynchAll);
|
||||||
|
|
||||||
if (reason == ThreadWakeupReason::Timeout) {
|
if (reason == ThreadWakeupReason::Timeout) {
|
||||||
|
@ -556,7 +557,7 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle
|
||||||
// Add the thread to each of the objects' waiting threads.
|
// Add the thread to each of the objects' waiting threads.
|
||||||
for (std::size_t i = 0; i < objects.size(); ++i) {
|
for (std::size_t i = 0; i < objects.size(); ++i) {
|
||||||
WaitObject* object = objects[i].get();
|
WaitObject* object = objects[i].get();
|
||||||
object->AddWaitingThread(thread);
|
object->AddWaitingThread(SharedFrom(thread));
|
||||||
}
|
}
|
||||||
|
|
||||||
thread->wait_objects = std::move(objects);
|
thread->wait_objects = std::move(objects);
|
||||||
|
@ -567,8 +568,8 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle
|
||||||
// Create an event to wake the thread up after the specified nanosecond delay has passed
|
// Create an event to wake the thread up after the specified nanosecond delay has passed
|
||||||
thread->WakeAfterDelay(nano_seconds);
|
thread->WakeAfterDelay(nano_seconds);
|
||||||
|
|
||||||
thread->wakeup_callback = [](ThreadWakeupReason reason, SharedPtr<Thread> thread,
|
thread->wakeup_callback = [](ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||||
SharedPtr<WaitObject> object) {
|
std::shared_ptr<WaitObject> object) {
|
||||||
ASSERT(thread->status == ThreadStatus::WaitSynchAny);
|
ASSERT(thread->status == ThreadStatus::WaitSynchAny);
|
||||||
|
|
||||||
if (reason == ThreadWakeupReason::Timeout) {
|
if (reason == ThreadWakeupReason::Timeout) {
|
||||||
|
@ -593,8 +594,8 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle
|
||||||
}
|
}
|
||||||
|
|
||||||
static ResultCode ReceiveIPCRequest(Memory::MemorySystem& memory,
|
static ResultCode ReceiveIPCRequest(Memory::MemorySystem& memory,
|
||||||
SharedPtr<ServerSession> server_session,
|
std::shared_ptr<ServerSession> server_session,
|
||||||
SharedPtr<Thread> thread) {
|
std::shared_ptr<Thread> thread) {
|
||||||
if (server_session->parent->client == nullptr) {
|
if (server_session->parent->client == nullptr) {
|
||||||
return ERR_SESSION_CLOSED_BY_REMOTE;
|
return ERR_SESSION_CLOSED_BY_REMOTE;
|
||||||
}
|
}
|
||||||
|
@ -631,10 +632,10 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co
|
||||||
if (handle_count < 0)
|
if (handle_count < 0)
|
||||||
return ERR_OUT_OF_RANGE;
|
return ERR_OUT_OF_RANGE;
|
||||||
|
|
||||||
using ObjectPtr = SharedPtr<WaitObject>;
|
using ObjectPtr = std::shared_ptr<WaitObject>;
|
||||||
std::vector<ObjectPtr> objects(handle_count);
|
std::vector<ObjectPtr> objects(handle_count);
|
||||||
|
|
||||||
SharedPtr<Process> current_process = kernel.GetCurrentProcess();
|
std::shared_ptr<Process> current_process = kernel.GetCurrentProcess();
|
||||||
|
|
||||||
for (int i = 0; i < handle_count; ++i) {
|
for (int i = 0; i < handle_count; ++i) {
|
||||||
Handle handle = memory.Read32(handles_address + i * sizeof(Handle));
|
Handle handle = memory.Read32(handles_address + i * sizeof(Handle));
|
||||||
|
@ -670,8 +671,8 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co
|
||||||
VAddr target_address = request_thread->GetCommandBufferAddress();
|
VAddr target_address = request_thread->GetCommandBufferAddress();
|
||||||
|
|
||||||
ResultCode translation_result =
|
ResultCode translation_result =
|
||||||
TranslateCommandBuffer(memory, thread, request_thread, source_address, target_address,
|
TranslateCommandBuffer(memory, SharedFrom(thread), request_thread, source_address,
|
||||||
session->mapped_buffer_context, true);
|
target_address, session->mapped_buffer_context, true);
|
||||||
|
|
||||||
// Note: The real kernel seems to always panic if the Server->Client buffer translation
|
// Note: The real kernel seems to always panic if the Server->Client buffer translation
|
||||||
// fails for whatever reason.
|
// fails for whatever reason.
|
||||||
|
@ -706,7 +707,7 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
|
|
||||||
auto server_session = static_cast<ServerSession*>(object);
|
auto server_session = static_cast<ServerSession*>(object);
|
||||||
return ReceiveIPCRequest(memory, server_session, thread);
|
return ReceiveIPCRequest(memory, SharedFrom(server_session), SharedFrom(thread));
|
||||||
}
|
}
|
||||||
|
|
||||||
// No objects were ready to be acquired, prepare to suspend the thread.
|
// No objects were ready to be acquired, prepare to suspend the thread.
|
||||||
|
@ -717,14 +718,14 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co
|
||||||
// Add the thread to each of the objects' waiting threads.
|
// Add the thread to each of the objects' waiting threads.
|
||||||
for (std::size_t i = 0; i < objects.size(); ++i) {
|
for (std::size_t i = 0; i < objects.size(); ++i) {
|
||||||
WaitObject* object = objects[i].get();
|
WaitObject* object = objects[i].get();
|
||||||
object->AddWaitingThread(thread);
|
object->AddWaitingThread(SharedFrom(thread));
|
||||||
}
|
}
|
||||||
|
|
||||||
thread->wait_objects = std::move(objects);
|
thread->wait_objects = std::move(objects);
|
||||||
|
|
||||||
thread->wakeup_callback = [& memory = this->memory](ThreadWakeupReason reason,
|
thread->wakeup_callback = [& memory = this->memory](ThreadWakeupReason reason,
|
||||||
SharedPtr<Thread> thread,
|
std::shared_ptr<Thread> thread,
|
||||||
SharedPtr<WaitObject> object) {
|
std::shared_ptr<WaitObject> object) {
|
||||||
ASSERT(thread->status == ThreadStatus::WaitSynchAny);
|
ASSERT(thread->status == ThreadStatus::WaitSynchAny);
|
||||||
ASSERT(reason == ThreadWakeupReason::Signal);
|
ASSERT(reason == ThreadWakeupReason::Signal);
|
||||||
|
|
||||||
|
@ -750,7 +751,7 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co
|
||||||
|
|
||||||
/// Create an address arbiter (to allocate access to shared resources)
|
/// Create an address arbiter (to allocate access to shared resources)
|
||||||
ResultCode SVC::CreateAddressArbiter(Handle* out_handle) {
|
ResultCode SVC::CreateAddressArbiter(Handle* out_handle) {
|
||||||
SharedPtr<AddressArbiter> arbiter = kernel.CreateAddressArbiter();
|
std::shared_ptr<AddressArbiter> arbiter = kernel.CreateAddressArbiter();
|
||||||
CASCADE_RESULT(*out_handle,
|
CASCADE_RESULT(*out_handle,
|
||||||
kernel.GetCurrentProcess()->handle_table.Create(std::move(arbiter)));
|
kernel.GetCurrentProcess()->handle_table.Create(std::move(arbiter)));
|
||||||
LOG_TRACE(Kernel_SVC, "returned handle=0x{:08X}", *out_handle);
|
LOG_TRACE(Kernel_SVC, "returned handle=0x{:08X}", *out_handle);
|
||||||
|
@ -762,13 +763,13 @@ ResultCode SVC::ArbitrateAddress(Handle handle, u32 address, u32 type, u32 value
|
||||||
LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}, address=0x{:08X}, type=0x{:08X}, value=0x{:08X}",
|
LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}, address=0x{:08X}, type=0x{:08X}, value=0x{:08X}",
|
||||||
handle, address, type, value);
|
handle, address, type, value);
|
||||||
|
|
||||||
SharedPtr<AddressArbiter> arbiter =
|
std::shared_ptr<AddressArbiter> arbiter =
|
||||||
kernel.GetCurrentProcess()->handle_table.Get<AddressArbiter>(handle);
|
kernel.GetCurrentProcess()->handle_table.Get<AddressArbiter>(handle);
|
||||||
if (arbiter == nullptr)
|
if (arbiter == nullptr)
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
|
||||||
auto res =
|
auto res =
|
||||||
arbiter->ArbitrateAddress(kernel.GetThreadManager().GetCurrentThread(),
|
arbiter->ArbitrateAddress(SharedFrom(kernel.GetThreadManager().GetCurrentThread()),
|
||||||
static_cast<ArbitrationType>(type), address, value, nanoseconds);
|
static_cast<ArbitrationType>(type), address, value, nanoseconds);
|
||||||
|
|
||||||
// TODO(Subv): Identify in which specific cases this call should cause a reschedule.
|
// TODO(Subv): Identify in which specific cases this call should cause a reschedule.
|
||||||
|
@ -812,8 +813,8 @@ void SVC::OutputDebugString(VAddr address, s32 len) {
|
||||||
ResultCode SVC::GetResourceLimit(Handle* resource_limit, Handle process_handle) {
|
ResultCode SVC::GetResourceLimit(Handle* resource_limit, Handle process_handle) {
|
||||||
LOG_TRACE(Kernel_SVC, "called process=0x{:08X}", process_handle);
|
LOG_TRACE(Kernel_SVC, "called process=0x{:08X}", process_handle);
|
||||||
|
|
||||||
SharedPtr<Process> current_process = kernel.GetCurrentProcess();
|
std::shared_ptr<Process> current_process = kernel.GetCurrentProcess();
|
||||||
SharedPtr<Process> process = current_process->handle_table.Get<Process>(process_handle);
|
std::shared_ptr<Process> process = current_process->handle_table.Get<Process>(process_handle);
|
||||||
if (process == nullptr)
|
if (process == nullptr)
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
|
||||||
|
@ -828,7 +829,7 @@ ResultCode SVC::GetResourceLimitCurrentValues(VAddr values, Handle resource_limi
|
||||||
LOG_TRACE(Kernel_SVC, "called resource_limit={:08X}, names={:08X}, name_count={}",
|
LOG_TRACE(Kernel_SVC, "called resource_limit={:08X}, names={:08X}, name_count={}",
|
||||||
resource_limit_handle, names, name_count);
|
resource_limit_handle, names, name_count);
|
||||||
|
|
||||||
SharedPtr<ResourceLimit> resource_limit =
|
std::shared_ptr<ResourceLimit> resource_limit =
|
||||||
kernel.GetCurrentProcess()->handle_table.Get<ResourceLimit>(resource_limit_handle);
|
kernel.GetCurrentProcess()->handle_table.Get<ResourceLimit>(resource_limit_handle);
|
||||||
if (resource_limit == nullptr)
|
if (resource_limit == nullptr)
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
@ -848,7 +849,7 @@ ResultCode SVC::GetResourceLimitLimitValues(VAddr values, Handle resource_limit_
|
||||||
LOG_TRACE(Kernel_SVC, "called resource_limit={:08X}, names={:08X}, name_count={}",
|
LOG_TRACE(Kernel_SVC, "called resource_limit={:08X}, names={:08X}, name_count={}",
|
||||||
resource_limit_handle, names, name_count);
|
resource_limit_handle, names, name_count);
|
||||||
|
|
||||||
SharedPtr<ResourceLimit> resource_limit =
|
std::shared_ptr<ResourceLimit> resource_limit =
|
||||||
kernel.GetCurrentProcess()->handle_table.Get<ResourceLimit>(resource_limit_handle);
|
kernel.GetCurrentProcess()->handle_table.Get<ResourceLimit>(resource_limit_handle);
|
||||||
if (resource_limit == nullptr)
|
if (resource_limit == nullptr)
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
@ -871,9 +872,9 @@ ResultCode SVC::CreateThread(Handle* out_handle, u32 entry_point, u32 arg, VAddr
|
||||||
return ERR_OUT_OF_RANGE;
|
return ERR_OUT_OF_RANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<Process> current_process = kernel.GetCurrentProcess();
|
std::shared_ptr<Process> current_process = kernel.GetCurrentProcess();
|
||||||
|
|
||||||
SharedPtr<ResourceLimit>& resource_limit = current_process->resource_limit;
|
std::shared_ptr<ResourceLimit>& resource_limit = current_process->resource_limit;
|
||||||
if (resource_limit->GetMaxResourceValue(ResourceTypes::PRIORITY) > priority) {
|
if (resource_limit->GetMaxResourceValue(ResourceTypes::PRIORITY) > priority) {
|
||||||
return ERR_NOT_AUTHORIZED;
|
return ERR_NOT_AUTHORIZED;
|
||||||
}
|
}
|
||||||
|
@ -901,7 +902,7 @@ ResultCode SVC::CreateThread(Handle* out_handle, u32 entry_point, u32 arg, VAddr
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
CASCADE_RESULT(SharedPtr<Thread> thread,
|
CASCADE_RESULT(std::shared_ptr<Thread> thread,
|
||||||
kernel.CreateThread(name, entry_point, priority, arg, processor_id, stack_top,
|
kernel.CreateThread(name, entry_point, priority, arg, processor_id, stack_top,
|
||||||
*current_process));
|
*current_process));
|
||||||
|
|
||||||
|
@ -930,7 +931,8 @@ void SVC::ExitThread() {
|
||||||
|
|
||||||
/// Gets the priority for the specified thread
|
/// Gets the priority for the specified thread
|
||||||
ResultCode SVC::GetThreadPriority(u32* priority, Handle handle) {
|
ResultCode SVC::GetThreadPriority(u32* priority, Handle handle) {
|
||||||
const SharedPtr<Thread> thread = kernel.GetCurrentProcess()->handle_table.Get<Thread>(handle);
|
const std::shared_ptr<Thread> thread =
|
||||||
|
kernel.GetCurrentProcess()->handle_table.Get<Thread>(handle);
|
||||||
if (thread == nullptr)
|
if (thread == nullptr)
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
|
||||||
|
@ -944,13 +946,13 @@ ResultCode SVC::SetThreadPriority(Handle handle, u32 priority) {
|
||||||
return ERR_OUT_OF_RANGE;
|
return ERR_OUT_OF_RANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<Thread> thread = kernel.GetCurrentProcess()->handle_table.Get<Thread>(handle);
|
std::shared_ptr<Thread> thread = kernel.GetCurrentProcess()->handle_table.Get<Thread>(handle);
|
||||||
if (thread == nullptr)
|
if (thread == nullptr)
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
|
||||||
// Note: The kernel uses the current process's resource limit instead of
|
// Note: The kernel uses the current process's resource limit instead of
|
||||||
// the one from the thread owner's resource limit.
|
// the one from the thread owner's resource limit.
|
||||||
SharedPtr<ResourceLimit>& resource_limit = kernel.GetCurrentProcess()->resource_limit;
|
std::shared_ptr<ResourceLimit>& resource_limit = kernel.GetCurrentProcess()->resource_limit;
|
||||||
if (resource_limit->GetMaxResourceValue(ResourceTypes::PRIORITY) > priority) {
|
if (resource_limit->GetMaxResourceValue(ResourceTypes::PRIORITY) > priority) {
|
||||||
return ERR_NOT_AUTHORIZED;
|
return ERR_NOT_AUTHORIZED;
|
||||||
}
|
}
|
||||||
|
@ -968,7 +970,7 @@ ResultCode SVC::SetThreadPriority(Handle handle, u32 priority) {
|
||||||
|
|
||||||
/// Create a mutex
|
/// Create a mutex
|
||||||
ResultCode SVC::CreateMutex(Handle* out_handle, u32 initial_locked) {
|
ResultCode SVC::CreateMutex(Handle* out_handle, u32 initial_locked) {
|
||||||
SharedPtr<Mutex> mutex = kernel.CreateMutex(initial_locked != 0);
|
std::shared_ptr<Mutex> mutex = kernel.CreateMutex(initial_locked != 0);
|
||||||
mutex->name = fmt::format("mutex-{:08x}", system.CPU().GetReg(14));
|
mutex->name = fmt::format("mutex-{:08x}", system.CPU().GetReg(14));
|
||||||
CASCADE_RESULT(*out_handle, kernel.GetCurrentProcess()->handle_table.Create(std::move(mutex)));
|
CASCADE_RESULT(*out_handle, kernel.GetCurrentProcess()->handle_table.Create(std::move(mutex)));
|
||||||
|
|
||||||
|
@ -982,7 +984,7 @@ ResultCode SVC::CreateMutex(Handle* out_handle, u32 initial_locked) {
|
||||||
ResultCode SVC::ReleaseMutex(Handle handle) {
|
ResultCode SVC::ReleaseMutex(Handle handle) {
|
||||||
LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}", handle);
|
LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}", handle);
|
||||||
|
|
||||||
SharedPtr<Mutex> mutex = kernel.GetCurrentProcess()->handle_table.Get<Mutex>(handle);
|
std::shared_ptr<Mutex> mutex = kernel.GetCurrentProcess()->handle_table.Get<Mutex>(handle);
|
||||||
if (mutex == nullptr)
|
if (mutex == nullptr)
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
|
||||||
|
@ -993,7 +995,7 @@ ResultCode SVC::ReleaseMutex(Handle handle) {
|
||||||
ResultCode SVC::GetProcessId(u32* process_id, Handle process_handle) {
|
ResultCode SVC::GetProcessId(u32* process_id, Handle process_handle) {
|
||||||
LOG_TRACE(Kernel_SVC, "called process=0x{:08X}", process_handle);
|
LOG_TRACE(Kernel_SVC, "called process=0x{:08X}", process_handle);
|
||||||
|
|
||||||
const SharedPtr<Process> process =
|
const std::shared_ptr<Process> process =
|
||||||
kernel.GetCurrentProcess()->handle_table.Get<Process>(process_handle);
|
kernel.GetCurrentProcess()->handle_table.Get<Process>(process_handle);
|
||||||
if (process == nullptr)
|
if (process == nullptr)
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
@ -1006,12 +1008,12 @@ ResultCode SVC::GetProcessId(u32* process_id, Handle process_handle) {
|
||||||
ResultCode SVC::GetProcessIdOfThread(u32* process_id, Handle thread_handle) {
|
ResultCode SVC::GetProcessIdOfThread(u32* process_id, Handle thread_handle) {
|
||||||
LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
|
LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
|
||||||
|
|
||||||
const SharedPtr<Thread> thread =
|
const std::shared_ptr<Thread> thread =
|
||||||
kernel.GetCurrentProcess()->handle_table.Get<Thread>(thread_handle);
|
kernel.GetCurrentProcess()->handle_table.Get<Thread>(thread_handle);
|
||||||
if (thread == nullptr)
|
if (thread == nullptr)
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
|
||||||
const SharedPtr<Process> process = thread->owner_process;
|
const std::shared_ptr<Process> process = SharedFrom(thread->owner_process);
|
||||||
|
|
||||||
ASSERT_MSG(process != nullptr, "Invalid parent process for thread={:#010X}", thread_handle);
|
ASSERT_MSG(process != nullptr, "Invalid parent process for thread={:#010X}", thread_handle);
|
||||||
|
|
||||||
|
@ -1023,7 +1025,8 @@ ResultCode SVC::GetProcessIdOfThread(u32* process_id, Handle thread_handle) {
|
||||||
ResultCode SVC::GetThreadId(u32* thread_id, Handle handle) {
|
ResultCode SVC::GetThreadId(u32* thread_id, Handle handle) {
|
||||||
LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", handle);
|
LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", handle);
|
||||||
|
|
||||||
const SharedPtr<Thread> thread = kernel.GetCurrentProcess()->handle_table.Get<Thread>(handle);
|
const std::shared_ptr<Thread> thread =
|
||||||
|
kernel.GetCurrentProcess()->handle_table.Get<Thread>(handle);
|
||||||
if (thread == nullptr)
|
if (thread == nullptr)
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
|
||||||
|
@ -1033,7 +1036,7 @@ ResultCode SVC::GetThreadId(u32* thread_id, Handle handle) {
|
||||||
|
|
||||||
/// Creates a semaphore
|
/// Creates a semaphore
|
||||||
ResultCode SVC::CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max_count) {
|
ResultCode SVC::CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max_count) {
|
||||||
CASCADE_RESULT(SharedPtr<Semaphore> semaphore,
|
CASCADE_RESULT(std::shared_ptr<Semaphore> semaphore,
|
||||||
kernel.CreateSemaphore(initial_count, max_count));
|
kernel.CreateSemaphore(initial_count, max_count));
|
||||||
semaphore->name = fmt::format("semaphore-{:08x}", system.CPU().GetReg(14));
|
semaphore->name = fmt::format("semaphore-{:08x}", system.CPU().GetReg(14));
|
||||||
CASCADE_RESULT(*out_handle,
|
CASCADE_RESULT(*out_handle,
|
||||||
|
@ -1048,7 +1051,7 @@ ResultCode SVC::CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max_c
|
||||||
ResultCode SVC::ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {
|
ResultCode SVC::ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {
|
||||||
LOG_TRACE(Kernel_SVC, "called release_count={}, handle=0x{:08X}", release_count, handle);
|
LOG_TRACE(Kernel_SVC, "called release_count={}, handle=0x{:08X}", release_count, handle);
|
||||||
|
|
||||||
SharedPtr<Semaphore> semaphore =
|
std::shared_ptr<Semaphore> semaphore =
|
||||||
kernel.GetCurrentProcess()->handle_table.Get<Semaphore>(handle);
|
kernel.GetCurrentProcess()->handle_table.Get<Semaphore>(handle);
|
||||||
if (semaphore == nullptr)
|
if (semaphore == nullptr)
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
@ -1061,7 +1064,7 @@ ResultCode SVC::ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {
|
||||||
/// Query process memory
|
/// Query process memory
|
||||||
ResultCode SVC::QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_info,
|
ResultCode SVC::QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_info,
|
||||||
Handle process_handle, u32 addr) {
|
Handle process_handle, u32 addr) {
|
||||||
SharedPtr<Process> process =
|
std::shared_ptr<Process> process =
|
||||||
kernel.GetCurrentProcess()->handle_table.Get<Process>(process_handle);
|
kernel.GetCurrentProcess()->handle_table.Get<Process>(process_handle);
|
||||||
if (process == nullptr)
|
if (process == nullptr)
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
@ -1105,8 +1108,8 @@ ResultCode SVC::QueryMemory(MemoryInfo* memory_info, PageInfo* page_info, u32 ad
|
||||||
|
|
||||||
/// Create an event
|
/// Create an event
|
||||||
ResultCode SVC::CreateEvent(Handle* out_handle, u32 reset_type) {
|
ResultCode SVC::CreateEvent(Handle* out_handle, u32 reset_type) {
|
||||||
SharedPtr<Event> evt = kernel.CreateEvent(static_cast<ResetType>(reset_type),
|
std::shared_ptr<Event> evt = kernel.CreateEvent(
|
||||||
fmt::format("event-{:08x}", system.CPU().GetReg(14)));
|
static_cast<ResetType>(reset_type), fmt::format("event-{:08x}", system.CPU().GetReg(14)));
|
||||||
CASCADE_RESULT(*out_handle, kernel.GetCurrentProcess()->handle_table.Create(std::move(evt)));
|
CASCADE_RESULT(*out_handle, kernel.GetCurrentProcess()->handle_table.Create(std::move(evt)));
|
||||||
|
|
||||||
LOG_TRACE(Kernel_SVC, "called reset_type=0x{:08X} : created handle=0x{:08X}", reset_type,
|
LOG_TRACE(Kernel_SVC, "called reset_type=0x{:08X} : created handle=0x{:08X}", reset_type,
|
||||||
|
@ -1125,7 +1128,7 @@ ResultCode SVC::DuplicateHandle(Handle* out, Handle handle) {
|
||||||
ResultCode SVC::SignalEvent(Handle handle) {
|
ResultCode SVC::SignalEvent(Handle handle) {
|
||||||
LOG_TRACE(Kernel_SVC, "called event=0x{:08X}", handle);
|
LOG_TRACE(Kernel_SVC, "called event=0x{:08X}", handle);
|
||||||
|
|
||||||
SharedPtr<Event> evt = kernel.GetCurrentProcess()->handle_table.Get<Event>(handle);
|
std::shared_ptr<Event> evt = kernel.GetCurrentProcess()->handle_table.Get<Event>(handle);
|
||||||
if (evt == nullptr)
|
if (evt == nullptr)
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
|
||||||
|
@ -1138,7 +1141,7 @@ ResultCode SVC::SignalEvent(Handle handle) {
|
||||||
ResultCode SVC::ClearEvent(Handle handle) {
|
ResultCode SVC::ClearEvent(Handle handle) {
|
||||||
LOG_TRACE(Kernel_SVC, "called event=0x{:08X}", handle);
|
LOG_TRACE(Kernel_SVC, "called event=0x{:08X}", handle);
|
||||||
|
|
||||||
SharedPtr<Event> evt = kernel.GetCurrentProcess()->handle_table.Get<Event>(handle);
|
std::shared_ptr<Event> evt = kernel.GetCurrentProcess()->handle_table.Get<Event>(handle);
|
||||||
if (evt == nullptr)
|
if (evt == nullptr)
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
|
||||||
|
@ -1148,7 +1151,7 @@ ResultCode SVC::ClearEvent(Handle handle) {
|
||||||
|
|
||||||
/// Creates a timer
|
/// Creates a timer
|
||||||
ResultCode SVC::CreateTimer(Handle* out_handle, u32 reset_type) {
|
ResultCode SVC::CreateTimer(Handle* out_handle, u32 reset_type) {
|
||||||
SharedPtr<Timer> timer = kernel.CreateTimer(
|
std::shared_ptr<Timer> timer = kernel.CreateTimer(
|
||||||
static_cast<ResetType>(reset_type), fmt ::format("timer-{:08x}", system.CPU().GetReg(14)));
|
static_cast<ResetType>(reset_type), fmt ::format("timer-{:08x}", system.CPU().GetReg(14)));
|
||||||
CASCADE_RESULT(*out_handle, kernel.GetCurrentProcess()->handle_table.Create(std::move(timer)));
|
CASCADE_RESULT(*out_handle, kernel.GetCurrentProcess()->handle_table.Create(std::move(timer)));
|
||||||
|
|
||||||
|
@ -1161,7 +1164,7 @@ ResultCode SVC::CreateTimer(Handle* out_handle, u32 reset_type) {
|
||||||
ResultCode SVC::ClearTimer(Handle handle) {
|
ResultCode SVC::ClearTimer(Handle handle) {
|
||||||
LOG_TRACE(Kernel_SVC, "called timer=0x{:08X}", handle);
|
LOG_TRACE(Kernel_SVC, "called timer=0x{:08X}", handle);
|
||||||
|
|
||||||
SharedPtr<Timer> timer = kernel.GetCurrentProcess()->handle_table.Get<Timer>(handle);
|
std::shared_ptr<Timer> timer = kernel.GetCurrentProcess()->handle_table.Get<Timer>(handle);
|
||||||
if (timer == nullptr)
|
if (timer == nullptr)
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
|
||||||
|
@ -1177,7 +1180,7 @@ ResultCode SVC::SetTimer(Handle handle, s64 initial, s64 interval) {
|
||||||
return ERR_OUT_OF_RANGE_KERNEL;
|
return ERR_OUT_OF_RANGE_KERNEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<Timer> timer = kernel.GetCurrentProcess()->handle_table.Get<Timer>(handle);
|
std::shared_ptr<Timer> timer = kernel.GetCurrentProcess()->handle_table.Get<Timer>(handle);
|
||||||
if (timer == nullptr)
|
if (timer == nullptr)
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
|
||||||
|
@ -1190,7 +1193,7 @@ ResultCode SVC::SetTimer(Handle handle, s64 initial, s64 interval) {
|
||||||
ResultCode SVC::CancelTimer(Handle handle) {
|
ResultCode SVC::CancelTimer(Handle handle) {
|
||||||
LOG_TRACE(Kernel_SVC, "called timer=0x{:08X}", handle);
|
LOG_TRACE(Kernel_SVC, "called timer=0x{:08X}", handle);
|
||||||
|
|
||||||
SharedPtr<Timer> timer = kernel.GetCurrentProcess()->handle_table.Get<Timer>(handle);
|
std::shared_ptr<Timer> timer = kernel.GetCurrentProcess()->handle_table.Get<Timer>(handle);
|
||||||
if (timer == nullptr)
|
if (timer == nullptr)
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
|
||||||
|
@ -1234,7 +1237,7 @@ ResultCode SVC::CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my
|
||||||
if (size % Memory::PAGE_SIZE != 0)
|
if (size % Memory::PAGE_SIZE != 0)
|
||||||
return ERR_MISALIGNED_SIZE;
|
return ERR_MISALIGNED_SIZE;
|
||||||
|
|
||||||
SharedPtr<SharedMemory> shared_memory = nullptr;
|
std::shared_ptr<SharedMemory> shared_memory = nullptr;
|
||||||
|
|
||||||
auto VerifyPermissions = [](MemoryPermission permission) {
|
auto VerifyPermissions = [](MemoryPermission permission) {
|
||||||
// SharedMemory blocks can not be created with Execute permissions
|
// SharedMemory blocks can not be created with Execute permissions
|
||||||
|
@ -1262,7 +1265,7 @@ ResultCode SVC::CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my
|
||||||
return ERR_INVALID_ADDRESS;
|
return ERR_INVALID_ADDRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<Process> current_process = kernel.GetCurrentProcess();
|
std::shared_ptr<Process> current_process = kernel.GetCurrentProcess();
|
||||||
|
|
||||||
// When trying to create a memory block with address = 0,
|
// When trying to create a memory block with address = 0,
|
||||||
// if the process has the Shared Device Memory flag in the exheader,
|
// if the process has the Shared Device Memory flag in the exheader,
|
||||||
|
@ -1287,23 +1290,23 @@ ResultCode SVC::CreatePort(Handle* server_port, Handle* client_port, VAddr name_
|
||||||
// TODO(Subv): Implement named ports.
|
// TODO(Subv): Implement named ports.
|
||||||
ASSERT_MSG(name_address == 0, "Named ports are currently unimplemented");
|
ASSERT_MSG(name_address == 0, "Named ports are currently unimplemented");
|
||||||
|
|
||||||
SharedPtr<Process> current_process = kernel.GetCurrentProcess();
|
std::shared_ptr<Process> current_process = kernel.GetCurrentProcess();
|
||||||
|
|
||||||
auto ports = kernel.CreatePortPair(max_sessions);
|
auto ports = kernel.CreatePortPair(max_sessions);
|
||||||
CASCADE_RESULT(*client_port, current_process->handle_table.Create(
|
CASCADE_RESULT(*client_port, current_process->handle_table.Create(
|
||||||
std::move(std::get<SharedPtr<ClientPort>>(ports))));
|
std::move(std::get<std::shared_ptr<ClientPort>>(ports))));
|
||||||
// Note: The 3DS kernel also leaks the client port handle if the server port handle fails to be
|
// Note: The 3DS kernel also leaks the client port handle if the server port handle fails to be
|
||||||
// created.
|
// created.
|
||||||
CASCADE_RESULT(*server_port, current_process->handle_table.Create(
|
CASCADE_RESULT(*server_port, current_process->handle_table.Create(
|
||||||
std::move(std::get<SharedPtr<ServerPort>>(ports))));
|
std::move(std::get<std::shared_ptr<ServerPort>>(ports))));
|
||||||
|
|
||||||
LOG_TRACE(Kernel_SVC, "called max_sessions={}", max_sessions);
|
LOG_TRACE(Kernel_SVC, "called max_sessions={}", max_sessions);
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode SVC::CreateSessionToPort(Handle* out_client_session, Handle client_port_handle) {
|
ResultCode SVC::CreateSessionToPort(Handle* out_client_session, Handle client_port_handle) {
|
||||||
SharedPtr<Process> current_process = kernel.GetCurrentProcess();
|
std::shared_ptr<Process> current_process = kernel.GetCurrentProcess();
|
||||||
SharedPtr<ClientPort> client_port =
|
std::shared_ptr<ClientPort> client_port =
|
||||||
current_process->handle_table.Get<ClientPort>(client_port_handle);
|
current_process->handle_table.Get<ClientPort>(client_port_handle);
|
||||||
if (client_port == nullptr)
|
if (client_port == nullptr)
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
@ -1316,12 +1319,12 @@ ResultCode SVC::CreateSessionToPort(Handle* out_client_session, Handle client_po
|
||||||
ResultCode SVC::CreateSession(Handle* server_session, Handle* client_session) {
|
ResultCode SVC::CreateSession(Handle* server_session, Handle* client_session) {
|
||||||
auto sessions = kernel.CreateSessionPair();
|
auto sessions = kernel.CreateSessionPair();
|
||||||
|
|
||||||
SharedPtr<Process> current_process = kernel.GetCurrentProcess();
|
std::shared_ptr<Process> current_process = kernel.GetCurrentProcess();
|
||||||
|
|
||||||
auto& server = std::get<SharedPtr<ServerSession>>(sessions);
|
auto& server = std::get<std::shared_ptr<ServerSession>>(sessions);
|
||||||
CASCADE_RESULT(*server_session, current_process->handle_table.Create(std::move(server)));
|
CASCADE_RESULT(*server_session, current_process->handle_table.Create(std::move(server)));
|
||||||
|
|
||||||
auto& client = std::get<SharedPtr<ClientSession>>(sessions);
|
auto& client = std::get<std::shared_ptr<ClientSession>>(sessions);
|
||||||
CASCADE_RESULT(*client_session, current_process->handle_table.Create(std::move(client)));
|
CASCADE_RESULT(*client_session, current_process->handle_table.Create(std::move(client)));
|
||||||
|
|
||||||
LOG_TRACE(Kernel_SVC, "called");
|
LOG_TRACE(Kernel_SVC, "called");
|
||||||
|
@ -1329,8 +1332,8 @@ ResultCode SVC::CreateSession(Handle* server_session, Handle* client_session) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode SVC::AcceptSession(Handle* out_server_session, Handle server_port_handle) {
|
ResultCode SVC::AcceptSession(Handle* out_server_session, Handle server_port_handle) {
|
||||||
SharedPtr<Process> current_process = kernel.GetCurrentProcess();
|
std::shared_ptr<Process> current_process = kernel.GetCurrentProcess();
|
||||||
SharedPtr<ServerPort> server_port =
|
std::shared_ptr<ServerPort> server_port =
|
||||||
current_process->handle_table.Get<ServerPort>(server_port_handle);
|
current_process->handle_table.Get<ServerPort>(server_port_handle);
|
||||||
if (server_port == nullptr)
|
if (server_port == nullptr)
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
@ -1386,7 +1389,7 @@ ResultCode SVC::GetSystemInfo(s64* out, u32 type, s32 param) {
|
||||||
ResultCode SVC::GetProcessInfo(s64* out, Handle process_handle, u32 type) {
|
ResultCode SVC::GetProcessInfo(s64* out, Handle process_handle, u32 type) {
|
||||||
LOG_TRACE(Kernel_SVC, "called process=0x{:08X} type={}", process_handle, type);
|
LOG_TRACE(Kernel_SVC, "called process=0x{:08X} type={}", process_handle, type);
|
||||||
|
|
||||||
SharedPtr<Process> process =
|
std::shared_ptr<Process> process =
|
||||||
kernel.GetCurrentProcess()->handle_table.Get<Process>(process_handle);
|
kernel.GetCurrentProcess()->handle_table.Get<Process>(process_handle);
|
||||||
if (process == nullptr)
|
if (process == nullptr)
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
|
|
@ -105,13 +105,13 @@ void ThreadManager::SwitchContext(Thread* new_thread) {
|
||||||
|
|
||||||
auto previous_process = kernel.GetCurrentProcess();
|
auto previous_process = kernel.GetCurrentProcess();
|
||||||
|
|
||||||
current_thread = new_thread;
|
current_thread = SharedFrom(new_thread);
|
||||||
|
|
||||||
ready_queue.remove(new_thread->current_priority, new_thread);
|
ready_queue.remove(new_thread->current_priority, new_thread);
|
||||||
new_thread->status = ThreadStatus::Running;
|
new_thread->status = ThreadStatus::Running;
|
||||||
|
|
||||||
if (previous_process != current_thread->owner_process) {
|
if (previous_process.get() != current_thread->owner_process) {
|
||||||
kernel.SetCurrentProcess(current_thread->owner_process);
|
kernel.SetCurrentProcess(SharedFrom(current_thread->owner_process));
|
||||||
kernel.memory.SetCurrentPageTable(
|
kernel.memory.SetCurrentPageTable(
|
||||||
¤t_thread->owner_process->vm_manager.page_table);
|
¤t_thread->owner_process->vm_manager.page_table);
|
||||||
}
|
}
|
||||||
|
@ -152,12 +152,13 @@ void ThreadManager::WaitCurrentThread_Sleep() {
|
||||||
void ThreadManager::ExitCurrentThread() {
|
void ThreadManager::ExitCurrentThread() {
|
||||||
Thread* thread = GetCurrentThread();
|
Thread* thread = GetCurrentThread();
|
||||||
thread->Stop();
|
thread->Stop();
|
||||||
thread_list.erase(std::remove(thread_list.begin(), thread_list.end(), thread),
|
thread_list.erase(std::remove_if(thread_list.begin(), thread_list.end(),
|
||||||
|
[thread](const auto& p) { return p.get() == thread; }),
|
||||||
thread_list.end());
|
thread_list.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadManager::ThreadWakeupCallback(u64 thread_id, s64 cycles_late) {
|
void ThreadManager::ThreadWakeupCallback(u64 thread_id, s64 cycles_late) {
|
||||||
SharedPtr<Thread> thread = wakeup_callback_table.at(thread_id);
|
std::shared_ptr<Thread> thread = SharedFrom(wakeup_callback_table.at(thread_id));
|
||||||
if (thread == nullptr) {
|
if (thread == nullptr) {
|
||||||
LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", thread_id);
|
LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", thread_id);
|
||||||
return;
|
return;
|
||||||
|
@ -286,9 +287,10 @@ static void ResetThreadContext(const std::unique_ptr<ARM_Interface::ThreadContex
|
||||||
context->SetCpsr(USER32MODE | ((entry_point & 1) << 5)); // Usermode and THUMB mode
|
context->SetCpsr(USER32MODE | ((entry_point & 1) << 5)); // Usermode and THUMB mode
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultVal<SharedPtr<Thread>> KernelSystem::CreateThread(std::string name, VAddr entry_point,
|
ResultVal<std::shared_ptr<Thread>> KernelSystem::CreateThread(std::string name, VAddr entry_point,
|
||||||
u32 priority, u32 arg, s32 processor_id,
|
u32 priority, u32 arg,
|
||||||
VAddr stack_top, Process& owner_process) {
|
s32 processor_id, VAddr stack_top,
|
||||||
|
Process& owner_process) {
|
||||||
// Check if priority is in ranged. Lowest priority -> highest priority id.
|
// Check if priority is in ranged. Lowest priority -> highest priority id.
|
||||||
if (priority > ThreadPrioLowest) {
|
if (priority > ThreadPrioLowest) {
|
||||||
LOG_ERROR(Kernel_SVC, "Invalid thread priority: {}", priority);
|
LOG_ERROR(Kernel_SVC, "Invalid thread priority: {}", priority);
|
||||||
|
@ -309,7 +311,7 @@ ResultVal<SharedPtr<Thread>> KernelSystem::CreateThread(std::string name, VAddr
|
||||||
ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
|
ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<Thread> thread(new Thread(*this));
|
auto thread{std::make_shared<Thread>(*this)};
|
||||||
|
|
||||||
thread_manager->thread_list.push_back(thread);
|
thread_manager->thread_list.push_back(thread);
|
||||||
thread_manager->ready_queue.prepare(priority);
|
thread_manager->ready_queue.prepare(priority);
|
||||||
|
@ -372,7 +374,7 @@ ResultVal<SharedPtr<Thread>> KernelSystem::CreateThread(std::string name, VAddr
|
||||||
thread_manager->ready_queue.push_back(thread->current_priority, thread.get());
|
thread_manager->ready_queue.push_back(thread->current_priority, thread.get());
|
||||||
thread->status = ThreadStatus::Ready;
|
thread->status = ThreadStatus::Ready;
|
||||||
|
|
||||||
return MakeResult<SharedPtr<Thread>>(std::move(thread));
|
return MakeResult<std::shared_ptr<Thread>>(std::move(thread));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Thread::SetPriority(u32 priority) {
|
void Thread::SetPriority(u32 priority) {
|
||||||
|
@ -405,14 +407,14 @@ void Thread::BoostPriority(u32 priority) {
|
||||||
current_priority = priority;
|
current_priority = priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<Thread> SetupMainThread(KernelSystem& kernel, u32 entry_point, u32 priority,
|
std::shared_ptr<Thread> SetupMainThread(KernelSystem& kernel, u32 entry_point, u32 priority,
|
||||||
SharedPtr<Process> owner_process) {
|
std::shared_ptr<Process> owner_process) {
|
||||||
// Initialize new "main" thread
|
// Initialize new "main" thread
|
||||||
auto thread_res =
|
auto thread_res =
|
||||||
kernel.CreateThread("main", entry_point, priority, 0, owner_process->ideal_processor,
|
kernel.CreateThread("main", entry_point, priority, 0, owner_process->ideal_processor,
|
||||||
Memory::HEAP_VADDR_END, *owner_process);
|
Memory::HEAP_VADDR_END, *owner_process);
|
||||||
|
|
||||||
SharedPtr<Thread> thread = std::move(thread_res).Unwrap();
|
std::shared_ptr<Thread> thread = std::move(thread_res).Unwrap();
|
||||||
|
|
||||||
thread->context->SetFpscr(FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO |
|
thread->context->SetFpscr(FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO |
|
||||||
FPSCR_IXC); // 0x03C00010
|
FPSCR_IXC); // 0x03C00010
|
||||||
|
@ -450,7 +452,8 @@ void Thread::SetWaitSynchronizationOutput(s32 output) {
|
||||||
|
|
||||||
s32 Thread::GetWaitObjectIndex(WaitObject* object) const {
|
s32 Thread::GetWaitObjectIndex(WaitObject* object) const {
|
||||||
ASSERT_MSG(!wait_objects.empty(), "Thread is not waiting for anything");
|
ASSERT_MSG(!wait_objects.empty(), "Thread is not waiting for anything");
|
||||||
auto match = std::find(wait_objects.rbegin(), wait_objects.rend(), object);
|
auto match = std::find_if(wait_objects.rbegin(), wait_objects.rend(),
|
||||||
|
[object](const auto& p) { return p.get() == object; });
|
||||||
return static_cast<s32>(std::distance(match, wait_objects.rend()) - 1);
|
return static_cast<s32>(std::distance(match, wait_objects.rend()) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,7 +476,7 @@ ThreadManager::~ThreadManager() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<SharedPtr<Thread>>& ThreadManager::GetThreadList() {
|
const std::vector<std::shared_ptr<Thread>>& ThreadManager::GetThreadList() {
|
||||||
return thread_list;
|
return thread_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Get a const reference to the thread list for debug use
|
* Get a const reference to the thread list for debug use
|
||||||
*/
|
*/
|
||||||
const std::vector<SharedPtr<Thread>>& GetThreadList();
|
const std::vector<std::shared_ptr<Thread>>& GetThreadList();
|
||||||
|
|
||||||
void SetCPU(ARM_Interface& cpu) {
|
void SetCPU(ARM_Interface& cpu) {
|
||||||
this->cpu = &cpu;
|
this->cpu = &cpu;
|
||||||
|
@ -133,7 +133,7 @@ private:
|
||||||
ARM_Interface* cpu;
|
ARM_Interface* cpu;
|
||||||
|
|
||||||
u32 next_thread_id = 1;
|
u32 next_thread_id = 1;
|
||||||
SharedPtr<Thread> current_thread;
|
std::shared_ptr<Thread> current_thread;
|
||||||
Common::ThreadQueueList<Thread*, ThreadPrioLowest + 1> ready_queue;
|
Common::ThreadQueueList<Thread*, ThreadPrioLowest + 1> ready_queue;
|
||||||
std::unordered_map<u64, Thread*> wakeup_callback_table;
|
std::unordered_map<u64, Thread*> wakeup_callback_table;
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ private:
|
||||||
Core::TimingEventType* ThreadWakeupEventType = nullptr;
|
Core::TimingEventType* ThreadWakeupEventType = nullptr;
|
||||||
|
|
||||||
// Lists all threadsthat aren't deleted.
|
// Lists all threadsthat aren't deleted.
|
||||||
std::vector<SharedPtr<Thread>> thread_list;
|
std::vector<std::shared_ptr<Thread>> thread_list;
|
||||||
|
|
||||||
friend class Thread;
|
friend class Thread;
|
||||||
friend class KernelSystem;
|
friend class KernelSystem;
|
||||||
|
@ -149,6 +149,9 @@ private:
|
||||||
|
|
||||||
class Thread final : public WaitObject {
|
class Thread final : public WaitObject {
|
||||||
public:
|
public:
|
||||||
|
explicit Thread(KernelSystem&);
|
||||||
|
~Thread() override;
|
||||||
|
|
||||||
std::string GetName() const override {
|
std::string GetName() const override {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
@ -278,35 +281,30 @@ public:
|
||||||
VAddr tls_address; ///< Virtual address of the Thread Local Storage of the thread
|
VAddr tls_address; ///< Virtual address of the Thread Local Storage of the thread
|
||||||
|
|
||||||
/// Mutexes currently held by this thread, which will be released when it exits.
|
/// Mutexes currently held by this thread, which will be released when it exits.
|
||||||
boost::container::flat_set<SharedPtr<Mutex>> held_mutexes;
|
boost::container::flat_set<std::shared_ptr<Mutex>> held_mutexes;
|
||||||
|
|
||||||
/// Mutexes that this thread is currently waiting for.
|
/// Mutexes that this thread is currently waiting for.
|
||||||
boost::container::flat_set<SharedPtr<Mutex>> pending_mutexes;
|
boost::container::flat_set<std::shared_ptr<Mutex>> pending_mutexes;
|
||||||
|
|
||||||
Process* owner_process; ///< Process that owns this thread
|
Process* owner_process; ///< Process that owns this thread
|
||||||
|
|
||||||
/// Objects that the thread is waiting on, in the same order as they were
|
/// Objects that the thread is waiting on, in the same order as they were
|
||||||
// passed to WaitSynchronization1/N.
|
// passed to WaitSynchronization1/N.
|
||||||
std::vector<SharedPtr<WaitObject>> wait_objects;
|
std::vector<std::shared_ptr<WaitObject>> wait_objects;
|
||||||
|
|
||||||
VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address
|
VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
using WakeupCallback = void(ThreadWakeupReason reason, SharedPtr<Thread> thread,
|
using WakeupCallback = void(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||||
SharedPtr<WaitObject> object);
|
std::shared_ptr<WaitObject> object);
|
||||||
// Callback that will be invoked when the thread is resumed from a waiting state. If the thread
|
// Callback that will be invoked when the thread is resumed from a waiting state. If the thread
|
||||||
// was waiting via WaitSynchronizationN then the object will be the last object that became
|
// was waiting via WaitSynchronizationN then the object will be the last object that became
|
||||||
// available. In case of a timeout, the object will be nullptr.
|
// available. In case of a timeout, the object will be nullptr.
|
||||||
std::function<WakeupCallback> wakeup_callback;
|
std::function<WakeupCallback> wakeup_callback;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit Thread(KernelSystem&);
|
|
||||||
~Thread() override;
|
|
||||||
|
|
||||||
ThreadManager& thread_manager;
|
ThreadManager& thread_manager;
|
||||||
|
|
||||||
friend class KernelSystem;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -317,7 +315,7 @@ private:
|
||||||
* @param owner_process The parent process for the main thread
|
* @param owner_process The parent process for the main thread
|
||||||
* @return A shared pointer to the main thread
|
* @return A shared pointer to the main thread
|
||||||
*/
|
*/
|
||||||
SharedPtr<Thread> SetupMainThread(KernelSystem& kernel, u32 entry_point, u32 priority,
|
std::shared_ptr<Thread> SetupMainThread(KernelSystem& kernel, u32 entry_point, u32 priority,
|
||||||
SharedPtr<Process> owner_process);
|
std::shared_ptr<Process> owner_process);
|
||||||
|
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
|
|
@ -21,8 +21,8 @@ Timer::~Timer() {
|
||||||
timer_manager.timer_callback_table.erase(callback_id);
|
timer_manager.timer_callback_table.erase(callback_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<Timer> KernelSystem::CreateTimer(ResetType reset_type, std::string name) {
|
std::shared_ptr<Timer> KernelSystem::CreateTimer(ResetType reset_type, std::string name) {
|
||||||
SharedPtr<Timer> timer(new Timer(*this));
|
auto timer{std::make_shared<Timer>(*this)};
|
||||||
|
|
||||||
timer->reset_type = reset_type;
|
timer->reset_type = reset_type;
|
||||||
timer->signaled = false;
|
timer->signaled = false;
|
||||||
|
@ -94,7 +94,7 @@ void Timer::Signal(s64 cycles_late) {
|
||||||
|
|
||||||
/// The timer callback event, called when a timer is fired
|
/// The timer callback event, called when a timer is fired
|
||||||
void TimerManager::TimerCallback(u64 callback_id, s64 cycles_late) {
|
void TimerManager::TimerCallback(u64 callback_id, s64 cycles_late) {
|
||||||
SharedPtr<Timer> timer = timer_callback_table.at(callback_id);
|
std::shared_ptr<Timer> timer = SharedFrom(timer_callback_table.at(callback_id));
|
||||||
|
|
||||||
if (timer == nullptr) {
|
if (timer == nullptr) {
|
||||||
LOG_CRITICAL(Kernel, "Callback fired for invalid timer {:016x}", callback_id);
|
LOG_CRITICAL(Kernel, "Callback fired for invalid timer {:016x}", callback_id);
|
||||||
|
|
|
@ -37,6 +37,9 @@ private:
|
||||||
|
|
||||||
class Timer final : public WaitObject {
|
class Timer final : public WaitObject {
|
||||||
public:
|
public:
|
||||||
|
explicit Timer(KernelSystem& kernel);
|
||||||
|
~Timer() override;
|
||||||
|
|
||||||
std::string GetTypeName() const override {
|
std::string GetTypeName() const override {
|
||||||
return "Timer";
|
return "Timer";
|
||||||
}
|
}
|
||||||
|
@ -85,9 +88,6 @@ public:
|
||||||
void Signal(s64 cycles_late);
|
void Signal(s64 cycles_late);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit Timer(KernelSystem& kernel);
|
|
||||||
~Timer() override;
|
|
||||||
|
|
||||||
ResetType reset_type; ///< The ResetType of this timer
|
ResetType reset_type; ///< The ResetType of this timer
|
||||||
|
|
||||||
u64 initial_delay; ///< The delay until the timer fires for the first time
|
u64 initial_delay; ///< The delay until the timer fires for the first time
|
||||||
|
|
|
@ -16,14 +16,15 @@
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
void WaitObject::AddWaitingThread(SharedPtr<Thread> thread) {
|
void WaitObject::AddWaitingThread(std::shared_ptr<Thread> thread) {
|
||||||
auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
|
auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
|
||||||
if (itr == waiting_threads.end())
|
if (itr == waiting_threads.end())
|
||||||
waiting_threads.push_back(std::move(thread));
|
waiting_threads.push_back(std::move(thread));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaitObject::RemoveWaitingThread(Thread* thread) {
|
void WaitObject::RemoveWaitingThread(Thread* thread) {
|
||||||
auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
|
auto itr = std::find_if(waiting_threads.begin(), waiting_threads.end(),
|
||||||
|
[thread](const auto& p) { return p.get() == thread; });
|
||||||
// If a thread passed multiple handles to the same object,
|
// If a thread passed multiple handles to the same object,
|
||||||
// the kernel might attempt to remove the thread from the object's
|
// the kernel might attempt to remove the thread from the object's
|
||||||
// waiting threads list multiple times.
|
// waiting threads list multiple times.
|
||||||
|
@ -31,7 +32,7 @@ void WaitObject::RemoveWaitingThread(Thread* thread) {
|
||||||
waiting_threads.erase(itr);
|
waiting_threads.erase(itr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
|
std::shared_ptr<Thread> WaitObject::GetHighestPriorityReadyThread() {
|
||||||
Thread* candidate = nullptr;
|
Thread* candidate = nullptr;
|
||||||
u32 candidate_priority = ThreadPrioLowest + 1;
|
u32 candidate_priority = ThreadPrioLowest + 1;
|
||||||
|
|
||||||
|
@ -53,7 +54,7 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
|
||||||
bool ready_to_run = true;
|
bool ready_to_run = true;
|
||||||
if (thread->status == ThreadStatus::WaitSynchAll) {
|
if (thread->status == ThreadStatus::WaitSynchAll) {
|
||||||
ready_to_run = std::none_of(thread->wait_objects.begin(), thread->wait_objects.end(),
|
ready_to_run = std::none_of(thread->wait_objects.begin(), thread->wait_objects.end(),
|
||||||
[&thread](const SharedPtr<WaitObject>& object) {
|
[&thread](const std::shared_ptr<WaitObject>& object) {
|
||||||
return object->ShouldWait(thread.get());
|
return object->ShouldWait(thread.get());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -64,7 +65,7 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return candidate;
|
return SharedFrom(candidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaitObject::WakeupAllWaitingThreads() {
|
void WaitObject::WakeupAllWaitingThreads() {
|
||||||
|
@ -79,7 +80,7 @@ void WaitObject::WakeupAllWaitingThreads() {
|
||||||
|
|
||||||
// Invoke the wakeup callback before clearing the wait objects
|
// Invoke the wakeup callback before clearing the wait objects
|
||||||
if (thread->wakeup_callback)
|
if (thread->wakeup_callback)
|
||||||
thread->wakeup_callback(ThreadWakeupReason::Signal, thread, this);
|
thread->wakeup_callback(ThreadWakeupReason::Signal, thread, SharedFrom(this));
|
||||||
|
|
||||||
for (auto& object : thread->wait_objects)
|
for (auto& object : thread->wait_objects)
|
||||||
object->RemoveWaitingThread(thread.get());
|
object->RemoveWaitingThread(thread.get());
|
||||||
|
@ -92,7 +93,7 @@ void WaitObject::WakeupAllWaitingThreads() {
|
||||||
hle_notifier();
|
hle_notifier();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<SharedPtr<Thread>>& WaitObject::GetWaitingThreads() const {
|
const std::vector<std::shared_ptr<Thread>>& WaitObject::GetWaitingThreads() const {
|
||||||
return waiting_threads;
|
return waiting_threads;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ public:
|
||||||
* Add a thread to wait on this object
|
* Add a thread to wait on this object
|
||||||
* @param thread Pointer to thread to add
|
* @param thread Pointer to thread to add
|
||||||
*/
|
*/
|
||||||
virtual void AddWaitingThread(SharedPtr<Thread> thread);
|
virtual void AddWaitingThread(std::shared_ptr<Thread> thread);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a thread from waiting on this object (e.g. if it was resumed already)
|
* Removes a thread from waiting on this object (e.g. if it was resumed already)
|
||||||
|
@ -48,17 +48,17 @@ public:
|
||||||
virtual void WakeupAllWaitingThreads();
|
virtual void WakeupAllWaitingThreads();
|
||||||
|
|
||||||
/// Obtains the highest priority thread that is ready to run from this object's waiting list.
|
/// Obtains the highest priority thread that is ready to run from this object's waiting list.
|
||||||
SharedPtr<Thread> GetHighestPriorityReadyThread();
|
std::shared_ptr<Thread> GetHighestPriorityReadyThread();
|
||||||
|
|
||||||
/// Get a const reference to the waiting threads list for debug use
|
/// Get a const reference to the waiting threads list for debug use
|
||||||
const std::vector<SharedPtr<Thread>>& GetWaitingThreads() const;
|
const std::vector<std::shared_ptr<Thread>>& GetWaitingThreads() const;
|
||||||
|
|
||||||
/// Sets a callback which is called when the object becomes available
|
/// Sets a callback which is called when the object becomes available
|
||||||
void SetHLENotifier(std::function<void()> callback);
|
void SetHLENotifier(std::function<void()> callback);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Threads waiting for this object to become available
|
/// Threads waiting for this object to become available
|
||||||
std::vector<SharedPtr<Thread>> waiting_threads;
|
std::vector<std::shared_ptr<Thread>> waiting_threads;
|
||||||
|
|
||||||
/// Function to call when this object becomes available
|
/// Function to call when this object becomes available
|
||||||
std::function<void()> hle_notifier;
|
std::function<void()> hle_notifier;
|
||||||
|
@ -66,9 +66,9 @@ private:
|
||||||
|
|
||||||
// Specialization of DynamicObjectCast for WaitObjects
|
// Specialization of DynamicObjectCast for WaitObjects
|
||||||
template <>
|
template <>
|
||||||
inline SharedPtr<WaitObject> DynamicObjectCast<WaitObject>(SharedPtr<Object> object) {
|
inline std::shared_ptr<WaitObject> DynamicObjectCast<WaitObject>(std::shared_ptr<Object> object) {
|
||||||
if (object != nullptr && object->IsWaitable()) {
|
if (object != nullptr && object->IsWaitable()) {
|
||||||
return boost::static_pointer_cast<WaitObject>(object);
|
return std::static_pointer_cast<WaitObject>(object);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,9 +151,9 @@ protected:
|
||||||
|
|
||||||
bool ac_connected = false;
|
bool ac_connected = false;
|
||||||
|
|
||||||
Kernel::SharedPtr<Kernel::Event> close_event;
|
std::shared_ptr<Kernel::Event> close_event;
|
||||||
Kernel::SharedPtr<Kernel::Event> connect_event;
|
std::shared_ptr<Kernel::Event> connect_event;
|
||||||
Kernel::SharedPtr<Kernel::Event> disconnect_event;
|
std::shared_ptr<Kernel::Event> disconnect_event;
|
||||||
};
|
};
|
||||||
|
|
||||||
void InstallInterfaces(Core::System& system);
|
void InstallInterfaces(Core::System& system);
|
||||||
|
|
|
@ -1138,7 +1138,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
ResultVal<std::unique_ptr<AMFileWrapper>> GetFileFromSession(
|
ResultVal<std::unique_ptr<AMFileWrapper>> GetFileFromSession(
|
||||||
Kernel::SharedPtr<Kernel::ClientSession> file_session) {
|
std::shared_ptr<Kernel::ClientSession> file_session) {
|
||||||
// Step up the chain from ClientSession->ServerSession and then
|
// Step up the chain from ClientSession->ServerSession and then
|
||||||
// cast to File. For AM on 3DS, invalid handles actually hang the system.
|
// cast to File. For AM on 3DS, invalid handles actually hang the system.
|
||||||
|
|
||||||
|
@ -1147,7 +1147,8 @@ ResultVal<std::unique_ptr<AMFileWrapper>> GetFileFromSession(
|
||||||
return Kernel::ERR_INVALID_HANDLE;
|
return Kernel::ERR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Kernel::SharedPtr<Kernel::ServerSession> server = file_session->parent->server;
|
std::shared_ptr<Kernel::ServerSession> server =
|
||||||
|
Kernel::SharedFrom(file_session->parent->server);
|
||||||
if (server == nullptr) {
|
if (server == nullptr) {
|
||||||
LOG_WARNING(Service_AM, "File handle ServerSession disconnected!");
|
LOG_WARNING(Service_AM, "File handle ServerSession disconnected!");
|
||||||
return Kernel::ERR_SESSION_CLOSED_BY_REMOTE;
|
return Kernel::ERR_SESSION_CLOSED_BY_REMOTE;
|
||||||
|
|
|
@ -576,7 +576,7 @@ private:
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
bool cia_installing = false;
|
bool cia_installing = false;
|
||||||
std::array<std::vector<u64_le>, 3> am_title_list;
|
std::array<std::vector<u64_le>, 3> am_title_list;
|
||||||
Kernel::SharedPtr<Kernel::Mutex> system_updater_mutex;
|
std::shared_ptr<Kernel::Mutex> system_updater_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
void InstallInterfaces(Core::System& system);
|
void InstallInterfaces(Core::System& system);
|
||||||
|
|
|
@ -384,7 +384,7 @@ ResultCode AppletManager::FinishPreloadingLibraryApplet(AppletId applet_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode AppletManager::StartLibraryApplet(AppletId applet_id,
|
ResultCode AppletManager::StartLibraryApplet(AppletId applet_id,
|
||||||
Kernel::SharedPtr<Kernel::Object> object,
|
std::shared_ptr<Kernel::Object> object,
|
||||||
const std::vector<u8>& buffer) {
|
const std::vector<u8>& buffer) {
|
||||||
MessageParameter param;
|
MessageParameter param;
|
||||||
param.destination_id = applet_id;
|
param.destination_id = applet_id;
|
||||||
|
@ -424,7 +424,7 @@ ResultCode AppletManager::PrepareToCloseLibraryApplet(bool not_pause, bool exiti
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode AppletManager::CloseLibraryApplet(Kernel::SharedPtr<Kernel::Object> object,
|
ResultCode AppletManager::CloseLibraryApplet(std::shared_ptr<Kernel::Object> object,
|
||||||
std::vector<u8> buffer) {
|
std::vector<u8> buffer) {
|
||||||
auto& slot = applet_slots[static_cast<std::size_t>(AppletSlot::LibraryApplet)];
|
auto& slot = applet_slots[static_cast<std::size_t>(AppletSlot::LibraryApplet)];
|
||||||
|
|
||||||
|
|
|
@ -81,13 +81,13 @@ struct MessageParameter {
|
||||||
AppletId sender_id = AppletId::None;
|
AppletId sender_id = AppletId::None;
|
||||||
AppletId destination_id = AppletId::None;
|
AppletId destination_id = AppletId::None;
|
||||||
SignalType signal = SignalType::None;
|
SignalType signal = SignalType::None;
|
||||||
Kernel::SharedPtr<Kernel::Object> object = nullptr;
|
std::shared_ptr<Kernel::Object> object = nullptr;
|
||||||
std::vector<u8> buffer;
|
std::vector<u8> buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Holds information about the parameters used in StartLibraryApplet
|
/// Holds information about the parameters used in StartLibraryApplet
|
||||||
struct AppletStartupParameter {
|
struct AppletStartupParameter {
|
||||||
Kernel::SharedPtr<Kernel::Object> object = nullptr;
|
std::shared_ptr<Kernel::Object> object = nullptr;
|
||||||
std::vector<u8> buffer;
|
std::vector<u8> buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -125,8 +125,8 @@ public:
|
||||||
AppletId receiver_appid);
|
AppletId receiver_appid);
|
||||||
|
|
||||||
struct InitializeResult {
|
struct InitializeResult {
|
||||||
Kernel::SharedPtr<Kernel::Event> notification_event;
|
std::shared_ptr<Kernel::Event> notification_event;
|
||||||
Kernel::SharedPtr<Kernel::Event> parameter_event;
|
std::shared_ptr<Kernel::Event> parameter_event;
|
||||||
};
|
};
|
||||||
|
|
||||||
ResultVal<InitializeResult> Initialize(AppletId app_id, AppletAttributes attributes);
|
ResultVal<InitializeResult> Initialize(AppletId app_id, AppletAttributes attributes);
|
||||||
|
@ -135,10 +135,10 @@ public:
|
||||||
ResultCode PrepareToStartLibraryApplet(AppletId applet_id);
|
ResultCode PrepareToStartLibraryApplet(AppletId applet_id);
|
||||||
ResultCode PreloadLibraryApplet(AppletId applet_id);
|
ResultCode PreloadLibraryApplet(AppletId applet_id);
|
||||||
ResultCode FinishPreloadingLibraryApplet(AppletId applet_id);
|
ResultCode FinishPreloadingLibraryApplet(AppletId applet_id);
|
||||||
ResultCode StartLibraryApplet(AppletId applet_id, Kernel::SharedPtr<Kernel::Object> object,
|
ResultCode StartLibraryApplet(AppletId applet_id, std::shared_ptr<Kernel::Object> object,
|
||||||
const std::vector<u8>& buffer);
|
const std::vector<u8>& buffer);
|
||||||
ResultCode PrepareToCloseLibraryApplet(bool not_pause, bool exiting, bool jump_home);
|
ResultCode PrepareToCloseLibraryApplet(bool not_pause, bool exiting, bool jump_home);
|
||||||
ResultCode CloseLibraryApplet(Kernel::SharedPtr<Kernel::Object> object, std::vector<u8> buffer);
|
ResultCode CloseLibraryApplet(std::shared_ptr<Kernel::Object> object, std::vector<u8> buffer);
|
||||||
|
|
||||||
ResultCode PrepareToDoApplicationJump(u64 title_id, FS::MediaType media_type,
|
ResultCode PrepareToDoApplicationJump(u64 title_id, FS::MediaType media_type,
|
||||||
ApplicationJumpFlags flags);
|
ApplicationJumpFlags flags);
|
||||||
|
@ -189,8 +189,8 @@ private:
|
||||||
bool registered;
|
bool registered;
|
||||||
bool loaded;
|
bool loaded;
|
||||||
AppletAttributes attributes;
|
AppletAttributes attributes;
|
||||||
Kernel::SharedPtr<Kernel::Event> notification_event;
|
std::shared_ptr<Kernel::Event> notification_event;
|
||||||
Kernel::SharedPtr<Kernel::Event> parameter_event;
|
std::shared_ptr<Kernel::Event> parameter_event;
|
||||||
|
|
||||||
void Reset() {
|
void Reset() {
|
||||||
applet_id = AppletId::None;
|
applet_id = AppletId::None;
|
||||||
|
|
|
@ -308,7 +308,7 @@ void Module::Interface::SendParameter(Kernel::HLERequestContext& ctx) {
|
||||||
AppletId dst_app_id = rp.PopEnum<AppletId>();
|
AppletId dst_app_id = rp.PopEnum<AppletId>();
|
||||||
SignalType signal_type = rp.PopEnum<SignalType>();
|
SignalType signal_type = rp.PopEnum<SignalType>();
|
||||||
u32 buffer_size = rp.Pop<u32>();
|
u32 buffer_size = rp.Pop<u32>();
|
||||||
Kernel::SharedPtr<Kernel::Object> object = rp.PopGenericObject();
|
std::shared_ptr<Kernel::Object> object = rp.PopGenericObject();
|
||||||
std::vector<u8> buffer = rp.PopStaticBuffer();
|
std::vector<u8> buffer = rp.PopStaticBuffer();
|
||||||
|
|
||||||
LOG_DEBUG(Service_APT,
|
LOG_DEBUG(Service_APT,
|
||||||
|
@ -586,7 +586,7 @@ void Module::Interface::StartLibraryApplet(Kernel::HLERequestContext& ctx) {
|
||||||
AppletId applet_id = rp.PopEnum<AppletId>();
|
AppletId applet_id = rp.PopEnum<AppletId>();
|
||||||
|
|
||||||
std::size_t buffer_size = rp.Pop<u32>();
|
std::size_t buffer_size = rp.Pop<u32>();
|
||||||
Kernel::SharedPtr<Kernel::Object> object = rp.PopGenericObject();
|
std::shared_ptr<Kernel::Object> object = rp.PopGenericObject();
|
||||||
std::vector<u8> buffer = rp.PopStaticBuffer();
|
std::vector<u8> buffer = rp.PopStaticBuffer();
|
||||||
|
|
||||||
LOG_DEBUG(Service_APT, "called, applet_id={:08X}", static_cast<u32>(applet_id));
|
LOG_DEBUG(Service_APT, "called, applet_id={:08X}", static_cast<u32>(applet_id));
|
||||||
|
@ -598,7 +598,7 @@ void Module::Interface::StartLibraryApplet(Kernel::HLERequestContext& ctx) {
|
||||||
void Module::Interface::CloseApplication(Kernel::HLERequestContext& ctx) {
|
void Module::Interface::CloseApplication(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp(ctx, 0x27, 1, 4);
|
IPC::RequestParser rp(ctx, 0x27, 1, 4);
|
||||||
u32 parameters_size = rp.Pop<u32>();
|
u32 parameters_size = rp.Pop<u32>();
|
||||||
Kernel::SharedPtr<Kernel::Object> object = rp.PopGenericObject();
|
std::shared_ptr<Kernel::Object> object = rp.PopGenericObject();
|
||||||
std::vector<u8> buffer = rp.PopStaticBuffer();
|
std::vector<u8> buffer = rp.PopStaticBuffer();
|
||||||
|
|
||||||
LOG_DEBUG(Service_APT, "called");
|
LOG_DEBUG(Service_APT, "called");
|
||||||
|
|
|
@ -603,11 +603,11 @@ private:
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
|
|
||||||
/// Handle to shared memory region designated to for shared system font
|
/// Handle to shared memory region designated to for shared system font
|
||||||
Kernel::SharedPtr<Kernel::SharedMemory> shared_font_mem;
|
std::shared_ptr<Kernel::SharedMemory> shared_font_mem;
|
||||||
bool shared_font_loaded = false;
|
bool shared_font_loaded = false;
|
||||||
bool shared_font_relocated = false;
|
bool shared_font_relocated = false;
|
||||||
|
|
||||||
Kernel::SharedPtr<Kernel::Mutex> lock;
|
std::shared_ptr<Kernel::Mutex> lock;
|
||||||
|
|
||||||
u32 cpu_percent = 0; ///< CPU time available to the running application
|
u32 cpu_percent = 0; ///< CPU time available to the running application
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
namespace Service::APT::BCFNT {
|
namespace Service::APT::BCFNT {
|
||||||
|
|
||||||
void RelocateSharedFont(Kernel::SharedPtr<Kernel::SharedMemory> shared_font, VAddr new_address) {
|
void RelocateSharedFont(std::shared_ptr<Kernel::SharedMemory> shared_font, VAddr new_address) {
|
||||||
static const u32 SharedFontStartOffset = 0x80;
|
static const u32 SharedFontStartOffset = 0x80;
|
||||||
const u8* cfnt_ptr = shared_font->GetPointer(SharedFontStartOffset);
|
const u8* cfnt_ptr = shared_font->GetPointer(SharedFontStartOffset);
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,6 @@ struct CWDH {
|
||||||
* @param shared_font SharedMemory object that contains the Shared Font
|
* @param shared_font SharedMemory object that contains the Shared Font
|
||||||
* @param new_address New base for the offsets in the structure.
|
* @param new_address New base for the offsets in the structure.
|
||||||
*/
|
*/
|
||||||
void RelocateSharedFont(Kernel::SharedPtr<Kernel::SharedMemory> shared_font, VAddr new_address);
|
void RelocateSharedFont(std::shared_ptr<Kernel::SharedMemory> shared_font, VAddr new_address);
|
||||||
|
|
||||||
} // namespace Service::APT::BCFNT
|
} // namespace Service::APT::BCFNT
|
||||||
|
|
|
@ -282,7 +282,7 @@ void Module::Interface::SendProperty(Kernel::HLERequestContext& ctx) {
|
||||||
void Module::Interface::SendPropertyHandle(Kernel::HLERequestContext& ctx) {
|
void Module::Interface::SendPropertyHandle(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp(ctx, 0x15, 1, 2);
|
IPC::RequestParser rp(ctx, 0x15, 1, 2);
|
||||||
const u16 property_id = rp.Pop<u16>();
|
const u16 property_id = rp.Pop<u16>();
|
||||||
const Kernel::SharedPtr<Kernel::Object> object = rp.PopGenericObject();
|
const std::shared_ptr<Kernel::Object> object = rp.PopGenericObject();
|
||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
rb.Push(RESULT_SUCCESS);
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
|
|
@ -961,7 +961,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Kernel::SharedPtr<Kernel::Event> task_finish_event;
|
std::shared_ptr<Kernel::Event> task_finish_event;
|
||||||
};
|
};
|
||||||
|
|
||||||
void InstallInterfaces(Core::System& system);
|
void InstallInterfaces(Core::System& system);
|
||||||
|
|
|
@ -765,9 +765,9 @@ private:
|
||||||
|
|
||||||
u16 transfer_bytes;
|
u16 transfer_bytes;
|
||||||
|
|
||||||
Kernel::SharedPtr<Kernel::Event> completion_event;
|
std::shared_ptr<Kernel::Event> completion_event;
|
||||||
Kernel::SharedPtr<Kernel::Event> buffer_error_interrupt_event;
|
std::shared_ptr<Kernel::Event> buffer_error_interrupt_event;
|
||||||
Kernel::SharedPtr<Kernel::Event> vsync_interrupt_event;
|
std::shared_ptr<Kernel::Event> vsync_interrupt_event;
|
||||||
|
|
||||||
std::future<std::vector<u16>> capture_result; // will hold the received frame.
|
std::future<std::vector<u16>> capture_result; // will hold the received frame.
|
||||||
Kernel::Process* dest_process;
|
Kernel::Process* dest_process;
|
||||||
|
|
|
@ -608,8 +608,8 @@ private:
|
||||||
|
|
||||||
std::unique_ptr<FileSys::ArchiveBackend> cecd_system_save_data_archive;
|
std::unique_ptr<FileSys::ArchiveBackend> cecd_system_save_data_archive;
|
||||||
|
|
||||||
Kernel::SharedPtr<Kernel::Event> cecinfo_event;
|
std::shared_ptr<Kernel::Event> cecinfo_event;
|
||||||
Kernel::SharedPtr<Kernel::Event> change_state_event;
|
std::shared_ptr<Kernel::Event> change_state_event;
|
||||||
|
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
};
|
};
|
||||||
|
|
|
@ -176,8 +176,8 @@ private:
|
||||||
|
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
|
|
||||||
Kernel::SharedPtr<Kernel::Mutex> mutex = nullptr;
|
std::shared_ptr<Kernel::Mutex> mutex = nullptr;
|
||||||
Kernel::SharedPtr<Kernel::SharedMemory> shared_memory = nullptr;
|
std::shared_ptr<Kernel::SharedMemory> shared_memory = nullptr;
|
||||||
|
|
||||||
static constexpr u32 MaxCaptureUnits = 2;
|
static constexpr u32 MaxCaptureUnits = 2;
|
||||||
std::array<bool, MaxCaptureUnits> capture_units = {false, false};
|
std::array<bool, MaxCaptureUnits> capture_units = {false, false};
|
||||||
|
|
|
@ -308,7 +308,7 @@ void DSP_DSP::SignalInterrupt(InterruptType type, DspPipe pipe) {
|
||||||
event->Signal();
|
event->Signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
Kernel::SharedPtr<Kernel::Event>& DSP_DSP::GetInterruptEvent(InterruptType type, DspPipe pipe) {
|
std::shared_ptr<Kernel::Event>& DSP_DSP::GetInterruptEvent(InterruptType type, DspPipe pipe) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case InterruptType::Zero:
|
case InterruptType::Zero:
|
||||||
return interrupt_zero;
|
return interrupt_zero;
|
||||||
|
|
|
@ -249,21 +249,20 @@ private:
|
||||||
void ForceHeadphoneOut(Kernel::HLERequestContext& ctx);
|
void ForceHeadphoneOut(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
/// Returns the Interrupt Event for a given pipe
|
/// Returns the Interrupt Event for a given pipe
|
||||||
Kernel::SharedPtr<Kernel::Event>& GetInterruptEvent(InterruptType type,
|
std::shared_ptr<Kernel::Event>& GetInterruptEvent(InterruptType type, AudioCore::DspPipe pipe);
|
||||||
AudioCore::DspPipe pipe);
|
|
||||||
/// Checks if we are trying to register more than 6 events
|
/// Checks if we are trying to register more than 6 events
|
||||||
bool HasTooManyEventsRegistered() const;
|
bool HasTooManyEventsRegistered() const;
|
||||||
|
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
|
|
||||||
Kernel::SharedPtr<Kernel::Event> semaphore_event;
|
std::shared_ptr<Kernel::Event> semaphore_event;
|
||||||
u16 preset_semaphore = 0;
|
u16 preset_semaphore = 0;
|
||||||
|
|
||||||
Kernel::SharedPtr<Kernel::Event> interrupt_zero = nullptr; /// Currently unknown purpose
|
std::shared_ptr<Kernel::Event> interrupt_zero = nullptr; /// Currently unknown purpose
|
||||||
Kernel::SharedPtr<Kernel::Event> interrupt_one = nullptr; /// Currently unknown purpose
|
std::shared_ptr<Kernel::Event> interrupt_one = nullptr; /// Currently unknown purpose
|
||||||
|
|
||||||
/// Each DSP pipe has an associated interrupt
|
/// Each DSP pipe has an associated interrupt
|
||||||
std::array<Kernel::SharedPtr<Kernel::Event>, AudioCore::num_dsp_pipe> pipes = {{}};
|
std::array<std::shared_ptr<Kernel::Event>, AudioCore::num_dsp_pipe> pipes = {{}};
|
||||||
};
|
};
|
||||||
|
|
||||||
void InstallInterfaces(Core::System& system);
|
void InstallInterfaces(Core::System& system);
|
||||||
|
|
|
@ -71,9 +71,10 @@ void File::Read(Kernel::HLERequestContext& ctx) {
|
||||||
rb.PushMappedBuffer(buffer);
|
rb.PushMappedBuffer(buffer);
|
||||||
|
|
||||||
std::chrono::nanoseconds read_timeout_ns{backend->GetReadDelayNs(length)};
|
std::chrono::nanoseconds read_timeout_ns{backend->GetReadDelayNs(length)};
|
||||||
ctx.SleepClientThread(
|
ctx.SleepClientThread(Kernel::SharedFrom(system.Kernel().GetThreadManager().GetCurrentThread()),
|
||||||
system.Kernel().GetThreadManager().GetCurrentThread(), "file::read", read_timeout_ns,
|
"file::read", read_timeout_ns,
|
||||||
[](Kernel::SharedPtr<Kernel::Thread> /*thread*/, Kernel::HLERequestContext& /*ctx*/,
|
[](std::shared_ptr<Kernel::Thread> /*thread*/,
|
||||||
|
Kernel::HLERequestContext& /*ctx*/,
|
||||||
Kernel::ThreadWakeupReason /*reason*/) {
|
Kernel::ThreadWakeupReason /*reason*/) {
|
||||||
// Nothing to do here
|
// Nothing to do here
|
||||||
});
|
});
|
||||||
|
@ -195,11 +196,11 @@ void File::OpenLinkFile(Kernel::HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile {}", GetName());
|
LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile {}", GetName());
|
||||||
using Kernel::ClientSession;
|
using Kernel::ClientSession;
|
||||||
using Kernel::ServerSession;
|
using Kernel::ServerSession;
|
||||||
using Kernel::SharedPtr;
|
using std::shared_ptr;
|
||||||
IPC::RequestParser rp(ctx, 0x080C, 0, 0);
|
IPC::RequestParser rp(ctx, 0x080C, 0, 0);
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
||||||
auto sessions = system.Kernel().CreateSessionPair(GetName());
|
auto sessions = system.Kernel().CreateSessionPair(GetName());
|
||||||
auto server = std::get<SharedPtr<ServerSession>>(sessions);
|
auto server = std::get<std::shared_ptr<ServerSession>>(sessions);
|
||||||
ClientConnected(server);
|
ClientConnected(server);
|
||||||
|
|
||||||
FileSessionSlot* slot = GetSessionData(server);
|
FileSessionSlot* slot = GetSessionData(server);
|
||||||
|
@ -211,7 +212,7 @@ void File::OpenLinkFile(Kernel::HLERequestContext& ctx) {
|
||||||
slot->subfile = false;
|
slot->subfile = false;
|
||||||
|
|
||||||
rb.Push(RESULT_SUCCESS);
|
rb.Push(RESULT_SUCCESS);
|
||||||
rb.PushMoveObjects(std::get<SharedPtr<ClientSession>>(sessions));
|
rb.PushMoveObjects(std::get<std::shared_ptr<ClientSession>>(sessions));
|
||||||
}
|
}
|
||||||
|
|
||||||
void File::OpenSubFile(Kernel::HLERequestContext& ctx) {
|
void File::OpenSubFile(Kernel::HLERequestContext& ctx) {
|
||||||
|
@ -245,9 +246,9 @@ void File::OpenSubFile(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
using Kernel::ClientSession;
|
using Kernel::ClientSession;
|
||||||
using Kernel::ServerSession;
|
using Kernel::ServerSession;
|
||||||
using Kernel::SharedPtr;
|
using std::shared_ptr;
|
||||||
auto sessions = system.Kernel().CreateSessionPair(GetName());
|
auto sessions = system.Kernel().CreateSessionPair(GetName());
|
||||||
auto server = std::get<SharedPtr<ServerSession>>(sessions);
|
auto server = std::get<std::shared_ptr<ServerSession>>(sessions);
|
||||||
ClientConnected(server);
|
ClientConnected(server);
|
||||||
|
|
||||||
FileSessionSlot* slot = GetSessionData(server);
|
FileSessionSlot* slot = GetSessionData(server);
|
||||||
|
@ -257,12 +258,12 @@ void File::OpenSubFile(Kernel::HLERequestContext& ctx) {
|
||||||
slot->subfile = true;
|
slot->subfile = true;
|
||||||
|
|
||||||
rb.Push(RESULT_SUCCESS);
|
rb.Push(RESULT_SUCCESS);
|
||||||
rb.PushMoveObjects(std::get<SharedPtr<ClientSession>>(sessions));
|
rb.PushMoveObjects(std::get<std::shared_ptr<ClientSession>>(sessions));
|
||||||
}
|
}
|
||||||
|
|
||||||
Kernel::SharedPtr<Kernel::ClientSession> File::Connect() {
|
std::shared_ptr<Kernel::ClientSession> File::Connect() {
|
||||||
auto sessions = system.Kernel().CreateSessionPair(GetName());
|
auto sessions = system.Kernel().CreateSessionPair(GetName());
|
||||||
auto server = std::get<Kernel::SharedPtr<Kernel::ServerSession>>(sessions);
|
auto server = std::get<std::shared_ptr<Kernel::ServerSession>>(sessions);
|
||||||
ClientConnected(server);
|
ClientConnected(server);
|
||||||
|
|
||||||
FileSessionSlot* slot = GetSessionData(server);
|
FileSessionSlot* slot = GetSessionData(server);
|
||||||
|
@ -271,16 +272,16 @@ Kernel::SharedPtr<Kernel::ClientSession> File::Connect() {
|
||||||
slot->size = backend->GetSize();
|
slot->size = backend->GetSize();
|
||||||
slot->subfile = false;
|
slot->subfile = false;
|
||||||
|
|
||||||
return std::get<Kernel::SharedPtr<Kernel::ClientSession>>(sessions);
|
return std::get<std::shared_ptr<Kernel::ClientSession>>(sessions);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t File::GetSessionFileOffset(Kernel::SharedPtr<Kernel::ServerSession> session) {
|
std::size_t File::GetSessionFileOffset(std::shared_ptr<Kernel::ServerSession> session) {
|
||||||
const FileSessionSlot* slot = GetSessionData(session);
|
const FileSessionSlot* slot = GetSessionData(session);
|
||||||
ASSERT(slot);
|
ASSERT(slot);
|
||||||
return slot->offset;
|
return slot->offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t File::GetSessionFileSize(Kernel::SharedPtr<Kernel::ServerSession> session) {
|
std::size_t File::GetSessionFileSize(std::shared_ptr<Kernel::ServerSession> session) {
|
||||||
const FileSessionSlot* slot = GetSessionData(session);
|
const FileSessionSlot* slot = GetSessionData(session);
|
||||||
ASSERT(slot);
|
ASSERT(slot);
|
||||||
return slot->size;
|
return slot->size;
|
||||||
|
|
|
@ -37,15 +37,15 @@ public:
|
||||||
std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface
|
std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface
|
||||||
|
|
||||||
/// Creates a new session to this File and returns the ClientSession part of the connection.
|
/// Creates a new session to this File and returns the ClientSession part of the connection.
|
||||||
Kernel::SharedPtr<Kernel::ClientSession> Connect();
|
std::shared_ptr<Kernel::ClientSession> Connect();
|
||||||
|
|
||||||
// Returns the start offset of an open file represented by the input session, opened with
|
// Returns the start offset of an open file represented by the input session, opened with
|
||||||
// OpenSubFile.
|
// OpenSubFile.
|
||||||
std::size_t GetSessionFileOffset(Kernel::SharedPtr<Kernel::ServerSession> session);
|
std::size_t GetSessionFileOffset(std::shared_ptr<Kernel::ServerSession> session);
|
||||||
|
|
||||||
// Returns the size of an open file represented by the input session, opened with
|
// Returns the size of an open file represented by the input session, opened with
|
||||||
// OpenSubFile.
|
// OpenSubFile.
|
||||||
std::size_t GetSessionFileSize(Kernel::SharedPtr<Kernel::ServerSession> session);
|
std::size_t GetSessionFileSize(std::shared_ptr<Kernel::ServerSession> session);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Read(Kernel::HLERequestContext& ctx);
|
void Read(Kernel::HLERequestContext& ctx);
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
using Kernel::ClientSession;
|
using Kernel::ClientSession;
|
||||||
using Kernel::ServerSession;
|
using Kernel::ServerSession;
|
||||||
using Kernel::SharedPtr;
|
using std::shared_ptr;
|
||||||
|
|
||||||
namespace Service::FS {
|
namespace Service::FS {
|
||||||
|
|
||||||
|
@ -72,9 +72,10 @@ void FS_USER::OpenFile(Kernel::HLERequestContext& ctx) {
|
||||||
LOG_ERROR(Service_FS, "failed to get a handle for file {}", file_path.DebugStr());
|
LOG_ERROR(Service_FS, "failed to get a handle for file {}", file_path.DebugStr());
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.SleepClientThread(
|
ctx.SleepClientThread(Kernel::SharedFrom(system.Kernel().GetThreadManager().GetCurrentThread()),
|
||||||
system.Kernel().GetThreadManager().GetCurrentThread(), "fs_user::open", open_timeout_ns,
|
"fs_user::open", open_timeout_ns,
|
||||||
[](Kernel::SharedPtr<Kernel::Thread> /*thread*/, Kernel::HLERequestContext& /*ctx*/,
|
[](std::shared_ptr<Kernel::Thread> /*thread*/,
|
||||||
|
Kernel::HLERequestContext& /*ctx*/,
|
||||||
Kernel::ThreadWakeupReason /*reason*/) {
|
Kernel::ThreadWakeupReason /*reason*/) {
|
||||||
// Nothing to do here
|
// Nothing to do here
|
||||||
});
|
});
|
||||||
|
@ -130,9 +131,9 @@ void FS_USER::OpenFileDirectly(Kernel::HLERequestContext& ctx) {
|
||||||
file_path.DebugStr(), mode.hex, attributes);
|
file_path.DebugStr(), mode.hex, attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.SleepClientThread(system.Kernel().GetThreadManager().GetCurrentThread(),
|
ctx.SleepClientThread(Kernel::SharedFrom(system.Kernel().GetThreadManager().GetCurrentThread()),
|
||||||
"fs_user::open_directly", open_timeout_ns,
|
"fs_user::open_directly", open_timeout_ns,
|
||||||
[](Kernel::SharedPtr<Kernel::Thread> /*thread*/,
|
[](std::shared_ptr<Kernel::Thread> /*thread*/,
|
||||||
Kernel::HLERequestContext& /*ctx*/,
|
Kernel::HLERequestContext& /*ctx*/,
|
||||||
Kernel::ThreadWakeupReason /*reason*/) {
|
Kernel::ThreadWakeupReason /*reason*/) {
|
||||||
// Nothing to do here
|
// Nothing to do here
|
||||||
|
@ -309,8 +310,8 @@ void FS_USER::OpenDirectory(Kernel::HLERequestContext& ctx) {
|
||||||
if (dir_res.Succeeded()) {
|
if (dir_res.Succeeded()) {
|
||||||
std::shared_ptr<Directory> directory = *dir_res;
|
std::shared_ptr<Directory> directory = *dir_res;
|
||||||
auto sessions = system.Kernel().CreateSessionPair(directory->GetName());
|
auto sessions = system.Kernel().CreateSessionPair(directory->GetName());
|
||||||
directory->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions));
|
directory->ClientConnected(std::get<std::shared_ptr<ServerSession>>(sessions));
|
||||||
rb.PushMoveObjects(std::get<SharedPtr<ClientSession>>(sessions));
|
rb.PushMoveObjects(std::get<std::shared_ptr<ClientSession>>(sessions));
|
||||||
} else {
|
} else {
|
||||||
LOG_ERROR(Service_FS, "failed to get a handle for directory type={} size={} data={}",
|
LOG_ERROR(Service_FS, "failed to get a handle for directory type={} size={} data={}",
|
||||||
static_cast<u32>(dirname_type), dirname_size, dir_path.DebugStr());
|
static_cast<u32>(dirname_type), dirname_size, dir_path.DebugStr());
|
||||||
|
|
|
@ -88,7 +88,7 @@ static u32 GetUnusedThreadId() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a pointer to a thread command buffer in GSP shared memory
|
/// Gets a pointer to a thread command buffer in GSP shared memory
|
||||||
static inline u8* GetCommandBuffer(Kernel::SharedPtr<Kernel::SharedMemory> shared_memory,
|
static inline u8* GetCommandBuffer(std::shared_ptr<Kernel::SharedMemory> shared_memory,
|
||||||
u32 thread_id) {
|
u32 thread_id) {
|
||||||
return shared_memory->GetPointer(0x800 + (thread_id * sizeof(CommandBuffer)));
|
return shared_memory->GetPointer(0x800 + (thread_id * sizeof(CommandBuffer)));
|
||||||
}
|
}
|
||||||
|
@ -104,12 +104,12 @@ FrameBufferUpdate* GSP_GPU::GetFrameBufferInfo(u32 thread_id, u32 screen_index)
|
||||||
|
|
||||||
/// Gets a pointer to the interrupt relay queue for a given thread index
|
/// Gets a pointer to the interrupt relay queue for a given thread index
|
||||||
static inline InterruptRelayQueue* GetInterruptRelayQueue(
|
static inline InterruptRelayQueue* GetInterruptRelayQueue(
|
||||||
Kernel::SharedPtr<Kernel::SharedMemory> shared_memory, u32 thread_id) {
|
std::shared_ptr<Kernel::SharedMemory> shared_memory, u32 thread_id) {
|
||||||
u8* ptr = shared_memory->GetPointer(sizeof(InterruptRelayQueue) * thread_id);
|
u8* ptr = shared_memory->GetPointer(sizeof(InterruptRelayQueue) * thread_id);
|
||||||
return reinterpret_cast<InterruptRelayQueue*>(ptr);
|
return reinterpret_cast<InterruptRelayQueue*>(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSP_GPU::ClientDisconnected(Kernel::SharedPtr<Kernel::ServerSession> server_session) {
|
void GSP_GPU::ClientDisconnected(std::shared_ptr<Kernel::ServerSession> server_session) {
|
||||||
SessionData* session_data = GetSessionData(server_session);
|
SessionData* session_data = GetSessionData(server_session);
|
||||||
if (active_thread_id == session_data->thread_id)
|
if (active_thread_id == session_data->thread_id)
|
||||||
ReleaseRight(session_data);
|
ReleaseRight(session_data);
|
||||||
|
|
|
@ -187,7 +187,7 @@ struct SessionData : public Kernel::SessionRequestHandler::SessionDataBase {
|
||||||
~SessionData();
|
~SessionData();
|
||||||
|
|
||||||
/// Event triggered when GSP interrupt has been signalled
|
/// Event triggered when GSP interrupt has been signalled
|
||||||
Kernel::SharedPtr<Kernel::Event> interrupt_event;
|
std::shared_ptr<Kernel::Event> interrupt_event;
|
||||||
/// Thread index into interrupt relay queue
|
/// Thread index into interrupt relay queue
|
||||||
u32 thread_id;
|
u32 thread_id;
|
||||||
/// Whether RegisterInterruptRelayQueue was called for this session
|
/// Whether RegisterInterruptRelayQueue was called for this session
|
||||||
|
@ -199,7 +199,7 @@ public:
|
||||||
explicit GSP_GPU(Core::System& system);
|
explicit GSP_GPU(Core::System& system);
|
||||||
~GSP_GPU() = default;
|
~GSP_GPU() = default;
|
||||||
|
|
||||||
void ClientDisconnected(Kernel::SharedPtr<Kernel::ServerSession> server_session) override;
|
void ClientDisconnected(std::shared_ptr<Kernel::ServerSession> server_session) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signals that the specified interrupt type has occurred to userland code
|
* Signals that the specified interrupt type has occurred to userland code
|
||||||
|
@ -406,7 +406,7 @@ private:
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
|
|
||||||
/// GSP shared memory
|
/// GSP shared memory
|
||||||
Kernel::SharedPtr<Kernel::SharedMemory> shared_memory;
|
std::shared_ptr<Kernel::SharedMemory> shared_memory;
|
||||||
|
|
||||||
/// Thread id that currently has GPU rights or -1 if none.
|
/// Thread id that currently has GPU rights or -1 if none.
|
||||||
int active_thread_id = -1;
|
int active_thread_id = -1;
|
||||||
|
|
|
@ -312,14 +312,14 @@ private:
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
|
|
||||||
// Handle to shared memory region designated to HID_User service
|
// Handle to shared memory region designated to HID_User service
|
||||||
Kernel::SharedPtr<Kernel::SharedMemory> shared_mem;
|
std::shared_ptr<Kernel::SharedMemory> shared_mem;
|
||||||
|
|
||||||
// Event handles
|
// Event handles
|
||||||
Kernel::SharedPtr<Kernel::Event> event_pad_or_touch_1;
|
std::shared_ptr<Kernel::Event> event_pad_or_touch_1;
|
||||||
Kernel::SharedPtr<Kernel::Event> event_pad_or_touch_2;
|
std::shared_ptr<Kernel::Event> event_pad_or_touch_2;
|
||||||
Kernel::SharedPtr<Kernel::Event> event_accelerometer;
|
std::shared_ptr<Kernel::Event> event_accelerometer;
|
||||||
Kernel::SharedPtr<Kernel::Event> event_gyroscope;
|
std::shared_ptr<Kernel::Event> event_gyroscope;
|
||||||
Kernel::SharedPtr<Kernel::Event> event_debug_pad;
|
std::shared_ptr<Kernel::Event> event_debug_pad;
|
||||||
|
|
||||||
// The HID module of a 3DS does not store the PadState.
|
// The HID module of a 3DS does not store the PadState.
|
||||||
// Storing this here was necessary for emulation specific tasks like cheats or scripting.
|
// Storing this here was necessary for emulation specific tasks like cheats or scripting.
|
||||||
|
|
|
@ -265,7 +265,7 @@ private:
|
||||||
|
|
||||||
void DecryptClCertA();
|
void DecryptClCertA();
|
||||||
|
|
||||||
Kernel::SharedPtr<Kernel::SharedMemory> shared_memory = nullptr;
|
std::shared_ptr<Kernel::SharedMemory> shared_memory = nullptr;
|
||||||
|
|
||||||
/// The next number to use when a new HTTP session is initalized.
|
/// The next number to use when a new HTTP session is initalized.
|
||||||
u32 session_counter = 0;
|
u32 session_counter = 0;
|
||||||
|
|
|
@ -78,8 +78,8 @@ private:
|
||||||
void UpdateCallback(u64 userdata, s64 cycles_late);
|
void UpdateCallback(u64 userdata, s64 cycles_late);
|
||||||
|
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
Kernel::SharedPtr<Kernel::Event> update_event;
|
std::shared_ptr<Kernel::Event> update_event;
|
||||||
Kernel::SharedPtr<Kernel::SharedMemory> shared_memory;
|
std::shared_ptr<Kernel::SharedMemory> shared_memory;
|
||||||
u32 next_pad_index{0};
|
u32 next_pad_index{0};
|
||||||
Core::TimingEventType* update_callback_id;
|
Core::TimingEventType* update_callback_id;
|
||||||
std::unique_ptr<Input::ButtonDevice> zl_button;
|
std::unique_ptr<Input::ButtonDevice> zl_button;
|
||||||
|
|
|
@ -66,7 +66,7 @@ static_assert(sizeof(SharedMemoryHeader) == 16, "SharedMemoryHeader has wrong si
|
||||||
*/
|
*/
|
||||||
class BufferManager {
|
class BufferManager {
|
||||||
public:
|
public:
|
||||||
BufferManager(Kernel::SharedPtr<Kernel::SharedMemory> shared_memory_, u32 info_offset_,
|
BufferManager(std::shared_ptr<Kernel::SharedMemory> shared_memory_, u32 info_offset_,
|
||||||
u32 buffer_offset_, u32 max_packet_count_, u32 buffer_size)
|
u32 buffer_offset_, u32 max_packet_count_, u32 buffer_size)
|
||||||
: shared_memory(shared_memory_), info_offset(info_offset_), buffer_offset(buffer_offset_),
|
: shared_memory(shared_memory_), info_offset(info_offset_), buffer_offset(buffer_offset_),
|
||||||
max_packet_count(max_packet_count_),
|
max_packet_count(max_packet_count_),
|
||||||
|
@ -174,7 +174,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferInfo info{0, 0, 0, 0};
|
BufferInfo info{0, 0, 0, 0};
|
||||||
Kernel::SharedPtr<Kernel::SharedMemory> shared_memory;
|
std::shared_ptr<Kernel::SharedMemory> shared_memory;
|
||||||
u32 info_offset;
|
u32 info_offset;
|
||||||
u32 buffer_offset;
|
u32 buffer_offset;
|
||||||
u32 max_packet_count;
|
u32 max_packet_count;
|
||||||
|
|
|
@ -162,8 +162,8 @@ private:
|
||||||
|
|
||||||
void PutToReceive(const std::vector<u8>& payload);
|
void PutToReceive(const std::vector<u8>& payload);
|
||||||
|
|
||||||
Kernel::SharedPtr<Kernel::Event> conn_status_event, send_event, receive_event;
|
std::shared_ptr<Kernel::Event> conn_status_event, send_event, receive_event;
|
||||||
Kernel::SharedPtr<Kernel::SharedMemory> shared_memory;
|
std::shared_ptr<Kernel::SharedMemory> shared_memory;
|
||||||
IRDevice* connected_device{nullptr};
|
IRDevice* connected_device{nullptr};
|
||||||
std::unique_ptr<BufferManager> receive_buffer;
|
std::unique_ptr<BufferManager> receive_buffer;
|
||||||
std::unique_ptr<ExtraHID> extra_hid;
|
std::unique_ptr<ExtraHID> extra_hid;
|
||||||
|
|
|
@ -354,9 +354,9 @@ struct MIC_U::Impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::atomic<bool> change_mic_impl_requested = false;
|
std::atomic<bool> change_mic_impl_requested = false;
|
||||||
Kernel::SharedPtr<Kernel::Event> buffer_full_event;
|
std::shared_ptr<Kernel::Event> buffer_full_event;
|
||||||
Core::TimingEventType* buffer_write_event = nullptr;
|
Core::TimingEventType* buffer_write_event = nullptr;
|
||||||
Kernel::SharedPtr<Kernel::SharedMemory> shared_memory;
|
std::shared_ptr<Kernel::SharedMemory> shared_memory;
|
||||||
u32 client_version = 0;
|
u32 client_version = 0;
|
||||||
bool allow_shell_closed = false;
|
bool allow_shell_closed = false;
|
||||||
bool clamp = false;
|
bool clamp = false;
|
||||||
|
|
|
@ -232,8 +232,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Kernel::SharedPtr<Kernel::Event> tag_in_range_event;
|
std::shared_ptr<Kernel::Event> tag_in_range_event;
|
||||||
Kernel::SharedPtr<Kernel::Event> tag_out_of_range_event;
|
std::shared_ptr<Kernel::Event> tag_out_of_range_event;
|
||||||
std::atomic<TagState> nfc_tag_state = TagState::NotInitialized;
|
std::atomic<TagState> nfc_tag_state = TagState::NotInitialized;
|
||||||
CommunicationStatus nfc_status = CommunicationStatus::NfcInitialized;
|
CommunicationStatus nfc_status = CommunicationStatus::NfcInitialized;
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ private:
|
||||||
*/
|
*/
|
||||||
void CheckSysUpdateAvailable(Kernel::HLERequestContext& ctx);
|
void CheckSysUpdateAvailable(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
Kernel::SharedPtr<Kernel::Event> nim_system_update_event;
|
std::shared_ptr<Kernel::Event> nim_system_update_event;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::NIM
|
} // namespace Service::NIM
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
namespace Service::NS {
|
namespace Service::NS {
|
||||||
|
|
||||||
Kernel::SharedPtr<Kernel::Process> LaunchTitle(FS::MediaType media_type, u64 title_id) {
|
std::shared_ptr<Kernel::Process> LaunchTitle(FS::MediaType media_type, u64 title_id) {
|
||||||
std::string path = AM::GetTitleContentPath(media_type, title_id);
|
std::string path = AM::GetTitleContentPath(media_type, title_id);
|
||||||
auto loader = Loader::GetLoader(path);
|
auto loader = Loader::GetLoader(path);
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ Kernel::SharedPtr<Kernel::Process> LaunchTitle(FS::MediaType media_type, u64 tit
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Kernel::SharedPtr<Kernel::Process> process;
|
std::shared_ptr<Kernel::Process> process;
|
||||||
Loader::ResultStatus result = loader->Load(process);
|
Loader::ResultStatus result = loader->Load(process);
|
||||||
|
|
||||||
if (result != Loader::ResultStatus::Success) {
|
if (result != Loader::ResultStatus::Success) {
|
||||||
|
|
|
@ -15,7 +15,7 @@ class System;
|
||||||
namespace Service::NS {
|
namespace Service::NS {
|
||||||
|
|
||||||
/// Loads and launches the title identified by title_id in the specified media type.
|
/// Loads and launches the title identified by title_id in the specified media type.
|
||||||
Kernel::SharedPtr<Kernel::Process> LaunchTitle(FS::MediaType media_type, u64 title_id);
|
std::shared_ptr<Kernel::Process> LaunchTitle(FS::MediaType media_type, u64 title_id);
|
||||||
|
|
||||||
/// Registers all NS services with the specified service manager.
|
/// Registers all NS services with the specified service manager.
|
||||||
void InstallInterfaces(Core::System& system);
|
void InstallInterfaces(Core::System& system);
|
||||||
|
|
|
@ -568,7 +568,7 @@ void NWM_UDS::RecvBeaconBroadcastData(Kernel::HLERequestContext& ctx) {
|
||||||
// 'Official user processes create a new event handle which is then passed to this command.
|
// 'Official user processes create a new event handle which is then passed to this command.
|
||||||
// However, those user processes don't save that handle anywhere afterwards.'
|
// However, those user processes don't save that handle anywhere afterwards.'
|
||||||
// So we don't save/use that event too.
|
// So we don't save/use that event too.
|
||||||
Kernel::SharedPtr<Kernel::Event> input_event = rp.PopObject<Kernel::Event>();
|
std::shared_ptr<Kernel::Event> input_event = rp.PopObject<Kernel::Event>();
|
||||||
|
|
||||||
Kernel::MappedBuffer out_buffer = rp.PopMappedBuffer();
|
Kernel::MappedBuffer out_buffer = rp.PopMappedBuffer();
|
||||||
ASSERT(out_buffer.GetSize() == out_buffer_size);
|
ASSERT(out_buffer.GetSize() == out_buffer_size);
|
||||||
|
@ -615,9 +615,9 @@ void NWM_UDS::RecvBeaconBroadcastData(Kernel::HLERequestContext& ctx) {
|
||||||
out_buffer_size, wlan_comm_id, id, unk1, unk2, cur_buffer_size);
|
out_buffer_size, wlan_comm_id, id, unk1, unk2, cur_buffer_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultVal<Kernel::SharedPtr<Kernel::Event>> NWM_UDS::Initialize(
|
ResultVal<std::shared_ptr<Kernel::Event>> NWM_UDS::Initialize(
|
||||||
u32 sharedmem_size, const NodeInfo& node, u16 version,
|
u32 sharedmem_size, const NodeInfo& node, u16 version,
|
||||||
Kernel::SharedPtr<Kernel::SharedMemory> sharedmem) {
|
std::shared_ptr<Kernel::SharedMemory> sharedmem) {
|
||||||
|
|
||||||
current_node = node;
|
current_node = node;
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
@ -1179,9 +1179,9 @@ void NWM_UDS::ConnectToNetwork(Kernel::HLERequestContext& ctx, u16 command_id,
|
||||||
static constexpr std::chrono::nanoseconds UDSConnectionTimeout{300000000};
|
static constexpr std::chrono::nanoseconds UDSConnectionTimeout{300000000};
|
||||||
|
|
||||||
connection_event = ctx.SleepClientThread(
|
connection_event = ctx.SleepClientThread(
|
||||||
system.Kernel().GetThreadManager().GetCurrentThread(), "uds::ConnectToNetwork",
|
Kernel::SharedFrom(system.Kernel().GetThreadManager().GetCurrentThread()),
|
||||||
UDSConnectionTimeout,
|
"uds::ConnectToNetwork", UDSConnectionTimeout,
|
||||||
[command_id](Kernel::SharedPtr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx,
|
[command_id](std::shared_ptr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx,
|
||||||
Kernel::ThreadWakeupReason reason) {
|
Kernel::ThreadWakeupReason reason) {
|
||||||
// TODO(B3N30): Add error handling for host full and timeout
|
// TODO(B3N30): Add error handling for host full and timeout
|
||||||
IPC::RequestBuilder rb(ctx, command_id, 1, 0);
|
IPC::RequestBuilder rb(ctx, command_id, 1, 0);
|
||||||
|
|
|
@ -416,9 +416,9 @@ private:
|
||||||
template <u16 command_id>
|
template <u16 command_id>
|
||||||
void DecryptBeaconData(Kernel::HLERequestContext& ctx);
|
void DecryptBeaconData(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
ResultVal<Kernel::SharedPtr<Kernel::Event>> Initialize(
|
ResultVal<std::shared_ptr<Kernel::Event>> Initialize(
|
||||||
u32 sharedmem_size, const NodeInfo& node, u16 version,
|
u32 sharedmem_size, const NodeInfo& node, u16 version,
|
||||||
Kernel::SharedPtr<Kernel::SharedMemory> sharedmem);
|
std::shared_ptr<Kernel::SharedMemory> sharedmem);
|
||||||
|
|
||||||
ResultCode BeginHostingNetwork(const u8* network_info_buffer, std::size_t network_info_size,
|
ResultCode BeginHostingNetwork(const u8* network_info_buffer, std::size_t network_info_size,
|
||||||
std::vector<u8> passphrase);
|
std::vector<u8> passphrase);
|
||||||
|
@ -477,11 +477,11 @@ private:
|
||||||
boost::optional<Network::MacAddress> GetNodeMacAddress(u16 dest_node_id, u8 flags);
|
boost::optional<Network::MacAddress> GetNodeMacAddress(u16 dest_node_id, u8 flags);
|
||||||
|
|
||||||
// Event that is signaled every time the connection status changes.
|
// Event that is signaled every time the connection status changes.
|
||||||
Kernel::SharedPtr<Kernel::Event> connection_status_event;
|
std::shared_ptr<Kernel::Event> connection_status_event;
|
||||||
|
|
||||||
// Shared memory provided by the application to store the receive buffer.
|
// Shared memory provided by the application to store the receive buffer.
|
||||||
// This is not currently used.
|
// This is not currently used.
|
||||||
Kernel::SharedPtr<Kernel::SharedMemory> recv_buffer_memory;
|
std::shared_ptr<Kernel::SharedMemory> recv_buffer_memory;
|
||||||
|
|
||||||
// Connection status of this 3DS.
|
// Connection status of this 3DS.
|
||||||
ConnectionStatus connection_status{};
|
ConnectionStatus connection_status{};
|
||||||
|
@ -503,7 +503,7 @@ private:
|
||||||
u8 channel; ///< Channel that this bind node was bound to.
|
u8 channel; ///< Channel that this bind node was bound to.
|
||||||
u16 network_node_id; ///< Node id this bind node is associated with, only packets from this
|
u16 network_node_id; ///< Node id this bind node is associated with, only packets from this
|
||||||
/// network node will be received.
|
/// network node will be received.
|
||||||
Kernel::SharedPtr<Kernel::Event> event; ///< Receive event for this bind node.
|
std::shared_ptr<Kernel::Event> event; ///< Receive event for this bind node.
|
||||||
std::deque<std::vector<u8>> received_packets; ///< List of packets received on this channel.
|
std::deque<std::vector<u8>> received_packets; ///< List of packets received on this channel.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -535,7 +535,7 @@ private:
|
||||||
// network thread.
|
// network thread.
|
||||||
std::mutex connection_status_mutex;
|
std::mutex connection_status_mutex;
|
||||||
|
|
||||||
Kernel::SharedPtr<Kernel::Event> connection_event;
|
std::shared_ptr<Kernel::Event> connection_event;
|
||||||
|
|
||||||
// Mutex to synchronize access to the list of received beacons between the emulation thread and
|
// Mutex to synchronize access to the list of received beacons between the emulation thread and
|
||||||
// the network thread.
|
// the network thread.
|
||||||
|
|
|
@ -197,7 +197,7 @@ static bool AttemptLLE(const ServiceModuleInfo& service_module) {
|
||||||
service_module.name);
|
service_module.name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Kernel::SharedPtr<Kernel::Process> process;
|
std::shared_ptr<Kernel::Process> process;
|
||||||
loader->Load(process);
|
loader->Load(process);
|
||||||
LOG_DEBUG(Service, "Service module \"{}\" has been successfully loaded.", service_module.name);
|
LOG_DEBUG(Service, "Service module \"{}\" has been successfully loaded.", service_module.name);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -159,7 +159,7 @@ protected:
|
||||||
return std::make_unique<SessionData>();
|
return std::make_unique<SessionData>();
|
||||||
}
|
}
|
||||||
|
|
||||||
SessionData* GetSessionData(Kernel::SharedPtr<Kernel::ServerSession> server_session) {
|
SessionData* GetSessionData(std::shared_ptr<Kernel::ServerSession> server_session) {
|
||||||
return ServiceFrameworkBase::GetSessionData<SessionData>(server_session);
|
return ServiceFrameworkBase::GetSessionData<SessionData>(server_session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ void ServiceManager::InstallInterfaces(Core::System& system) {
|
||||||
system.ServiceManager().srv_interface = srv;
|
system.ServiceManager().srv_interface = srv;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> ServiceManager::RegisterService(
|
ResultVal<std::shared_ptr<Kernel::ServerPort>> ServiceManager::RegisterService(
|
||||||
std::string name, unsigned int max_sessions) {
|
std::string name, unsigned int max_sessions) {
|
||||||
|
|
||||||
CASCADE_CODE(ValidateServiceName(name));
|
CASCADE_CODE(ValidateServiceName(name));
|
||||||
|
@ -46,7 +46,7 @@ ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> ServiceManager::RegisterService
|
||||||
return MakeResult(std::move(server_port));
|
return MakeResult(std::move(server_port));
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultVal<Kernel::SharedPtr<Kernel::ClientPort>> ServiceManager::GetServicePort(
|
ResultVal<std::shared_ptr<Kernel::ClientPort>> ServiceManager::GetServicePort(
|
||||||
const std::string& name) {
|
const std::string& name) {
|
||||||
|
|
||||||
CASCADE_CODE(ValidateServiceName(name));
|
CASCADE_CODE(ValidateServiceName(name));
|
||||||
|
@ -58,7 +58,7 @@ ResultVal<Kernel::SharedPtr<Kernel::ClientPort>> ServiceManager::GetServicePort(
|
||||||
return MakeResult(it->second);
|
return MakeResult(it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultVal<Kernel::SharedPtr<Kernel::ClientSession>> ServiceManager::ConnectToService(
|
ResultVal<std::shared_ptr<Kernel::ClientSession>> ServiceManager::ConnectToService(
|
||||||
const std::string& name) {
|
const std::string& name) {
|
||||||
|
|
||||||
CASCADE_RESULT(auto client_port, GetServicePort(name));
|
CASCADE_RESULT(auto client_port, GetServicePort(name));
|
||||||
|
|
|
@ -47,10 +47,10 @@ public:
|
||||||
|
|
||||||
explicit ServiceManager(Core::System& system);
|
explicit ServiceManager(Core::System& system);
|
||||||
|
|
||||||
ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> RegisterService(std::string name,
|
ResultVal<std::shared_ptr<Kernel::ServerPort>> RegisterService(std::string name,
|
||||||
unsigned int max_sessions);
|
unsigned int max_sessions);
|
||||||
ResultVal<Kernel::SharedPtr<Kernel::ClientPort>> GetServicePort(const std::string& name);
|
ResultVal<std::shared_ptr<Kernel::ClientPort>> GetServicePort(const std::string& name);
|
||||||
ResultVal<Kernel::SharedPtr<Kernel::ClientSession>> ConnectToService(const std::string& name);
|
ResultVal<std::shared_ptr<Kernel::ClientSession>> ConnectToService(const std::string& name);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::shared_ptr<T> GetService(const std::string& service_name) const {
|
std::shared_ptr<T> GetService(const std::string& service_name) const {
|
||||||
|
@ -73,7 +73,7 @@ private:
|
||||||
std::weak_ptr<SRV> srv_interface;
|
std::weak_ptr<SRV> srv_interface;
|
||||||
|
|
||||||
/// Map of registered services, retrieved using GetServicePort or ConnectToService.
|
/// Map of registered services, retrieved using GetServicePort or ConnectToService.
|
||||||
std::unordered_map<std::string, Kernel::SharedPtr<Kernel::ClientPort>> registered_services;
|
std::unordered_map<std::string, std::shared_ptr<Kernel::ClientPort>> registered_services;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::SM
|
} // namespace Service::SM
|
||||||
|
|
|
@ -100,7 +100,7 @@ void SRV::GetServiceHandle(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
// TODO(yuriks): Permission checks go here
|
// TODO(yuriks): Permission checks go here
|
||||||
|
|
||||||
auto get_handle = [name, this](Kernel::SharedPtr<Kernel::Thread> thread,
|
auto get_handle = [name, this](std::shared_ptr<Kernel::Thread> thread,
|
||||||
Kernel::HLERequestContext& ctx,
|
Kernel::HLERequestContext& ctx,
|
||||||
Kernel::ThreadWakeupReason reason) {
|
Kernel::ThreadWakeupReason reason) {
|
||||||
LOG_ERROR(Service_SRV, "called service={} wakeup", name);
|
LOG_ERROR(Service_SRV, "called service={} wakeup", name);
|
||||||
|
@ -127,8 +127,8 @@ void SRV::GetServiceHandle(Kernel::HLERequestContext& ctx) {
|
||||||
if (client_port.Failed()) {
|
if (client_port.Failed()) {
|
||||||
if (wait_until_available && client_port.Code() == ERR_SERVICE_NOT_REGISTERED) {
|
if (wait_until_available && client_port.Code() == ERR_SERVICE_NOT_REGISTERED) {
|
||||||
LOG_INFO(Service_SRV, "called service={} delayed", name);
|
LOG_INFO(Service_SRV, "called service={} delayed", name);
|
||||||
Kernel::SharedPtr<Kernel::Event> get_service_handle_event =
|
std::shared_ptr<Kernel::Event> get_service_handle_event = ctx.SleepClientThread(
|
||||||
ctx.SleepClientThread(system.Kernel().GetThreadManager().GetCurrentThread(),
|
Kernel::SharedFrom(system.Kernel().GetThreadManager().GetCurrentThread()),
|
||||||
"GetServiceHandle", std::chrono::nanoseconds(-1), get_handle);
|
"GetServiceHandle", std::chrono::nanoseconds(-1), get_handle);
|
||||||
get_service_handle_delayed_map[name] = std::move(get_service_handle_event);
|
get_service_handle_delayed_map[name] = std::move(get_service_handle_event);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -35,9 +35,8 @@ private:
|
||||||
void RegisterService(Kernel::HLERequestContext& ctx);
|
void RegisterService(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
Kernel::SharedPtr<Kernel::Semaphore> notification_semaphore;
|
std::shared_ptr<Kernel::Semaphore> notification_semaphore;
|
||||||
std::unordered_map<std::string, Kernel::SharedPtr<Kernel::Event>>
|
std::unordered_map<std::string, std::shared_ptr<Kernel::Event>> get_service_handle_delayed_map;
|
||||||
get_service_handle_delayed_map;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::SM
|
} // namespace Service::SM
|
||||||
|
|
|
@ -296,7 +296,7 @@ private:
|
||||||
|
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
|
|
||||||
Kernel::SharedPtr<Kernel::Event> completion_event;
|
std::shared_ptr<Kernel::Event> completion_event;
|
||||||
ConversionConfiguration conversion{};
|
ConversionConfiguration conversion{};
|
||||||
DitheringWeightParams dithering_weight_params{};
|
DitheringWeightParams dithering_weight_params{};
|
||||||
bool temporal_dithering_enabled = false;
|
bool temporal_dithering_enabled = false;
|
||||||
|
|
|
@ -92,10 +92,10 @@ static u32 TranslateAddr(u32 addr, const THREEloadinfo* loadinfo, u32* offsets)
|
||||||
}
|
}
|
||||||
|
|
||||||
using Kernel::CodeSet;
|
using Kernel::CodeSet;
|
||||||
using Kernel::SharedPtr;
|
using std::shared_ptr;
|
||||||
|
|
||||||
static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr,
|
static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr,
|
||||||
SharedPtr<CodeSet>* out_codeset) {
|
std::shared_ptr<CodeSet>* out_codeset) {
|
||||||
if (!file.IsOpen())
|
if (!file.IsOpen())
|
||||||
return ERROR_FILE;
|
return ERROR_FILE;
|
||||||
|
|
||||||
|
@ -217,7 +217,7 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the CodeSet
|
// Create the CodeSet
|
||||||
SharedPtr<CodeSet> code_set = Core::System::GetInstance().Kernel().CreateCodeSet("", 0);
|
std::shared_ptr<CodeSet> code_set = Core::System::GetInstance().Kernel().CreateCodeSet("", 0);
|
||||||
|
|
||||||
code_set->CodeSegment().offset = loadinfo.seg_ptrs[0] - program_image.data();
|
code_set->CodeSegment().offset = loadinfo.seg_ptrs[0] - program_image.data();
|
||||||
code_set->CodeSegment().addr = loadinfo.seg_addrs[0];
|
code_set->CodeSegment().addr = loadinfo.seg_addrs[0];
|
||||||
|
@ -255,14 +255,14 @@ FileType AppLoader_THREEDSX::IdentifyType(FileUtil::IOFile& file) {
|
||||||
return FileType::Error;
|
return FileType::Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus AppLoader_THREEDSX::Load(Kernel::SharedPtr<Kernel::Process>& process) {
|
ResultStatus AppLoader_THREEDSX::Load(std::shared_ptr<Kernel::Process>& process) {
|
||||||
if (is_loaded)
|
if (is_loaded)
|
||||||
return ResultStatus::ErrorAlreadyLoaded;
|
return ResultStatus::ErrorAlreadyLoaded;
|
||||||
|
|
||||||
if (!file.IsOpen())
|
if (!file.IsOpen())
|
||||||
return ResultStatus::Error;
|
return ResultStatus::Error;
|
||||||
|
|
||||||
SharedPtr<CodeSet> codeset;
|
std::shared_ptr<CodeSet> codeset;
|
||||||
if (Load3DSXFile(file, Memory::PROCESS_IMAGE_VADDR, &codeset) != ERROR_NONE)
|
if (Load3DSXFile(file, Memory::PROCESS_IMAGE_VADDR, &codeset) != ERROR_NONE)
|
||||||
return ResultStatus::Error;
|
return ResultStatus::Error;
|
||||||
codeset->name = filename;
|
codeset->name = filename;
|
||||||
|
|
|
@ -31,7 +31,7 @@ public:
|
||||||
return IdentifyType(file);
|
return IdentifyType(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
|
ResultStatus Load(std::shared_ptr<Kernel::Process>& process) override;
|
||||||
|
|
||||||
ResultStatus ReadIcon(std::vector<u8>& buffer) override;
|
ResultStatus ReadIcon(std::vector<u8>& buffer) override;
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
|
||||||
using Kernel::CodeSet;
|
using Kernel::CodeSet;
|
||||||
using Kernel::SharedPtr;
|
using std::shared_ptr;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// ELF Header Constants
|
// ELF Header Constants
|
||||||
|
@ -209,7 +209,7 @@ public:
|
||||||
u32 GetFlags() const {
|
u32 GetFlags() const {
|
||||||
return (u32)(header->e_flags);
|
return (u32)(header->e_flags);
|
||||||
}
|
}
|
||||||
SharedPtr<CodeSet> LoadInto(u32 vaddr);
|
std::shared_ptr<CodeSet> LoadInto(u32 vaddr);
|
||||||
|
|
||||||
int GetNumSegments() const {
|
int GetNumSegments() const {
|
||||||
return (int)(header->e_phnum);
|
return (int)(header->e_phnum);
|
||||||
|
@ -272,7 +272,7 @@ const char* ElfReader::GetSectionName(int section) const {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) {
|
std::shared_ptr<CodeSet> ElfReader::LoadInto(u32 vaddr) {
|
||||||
LOG_DEBUG(Loader, "String section: {}", header->e_shstrndx);
|
LOG_DEBUG(Loader, "String section: {}", header->e_shstrndx);
|
||||||
|
|
||||||
// Should we relocate?
|
// Should we relocate?
|
||||||
|
@ -300,7 +300,7 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) {
|
||||||
std::vector<u8> program_image(total_image_size);
|
std::vector<u8> program_image(total_image_size);
|
||||||
std::size_t current_image_position = 0;
|
std::size_t current_image_position = 0;
|
||||||
|
|
||||||
SharedPtr<CodeSet> codeset = Core::System::GetInstance().Kernel().CreateCodeSet("", 0);
|
std::shared_ptr<CodeSet> codeset = Core::System::GetInstance().Kernel().CreateCodeSet("", 0);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < header->e_phnum; ++i) {
|
for (unsigned int i = 0; i < header->e_phnum; ++i) {
|
||||||
Elf32_Phdr* p = &segments[i];
|
Elf32_Phdr* p = &segments[i];
|
||||||
|
@ -377,7 +377,7 @@ FileType AppLoader_ELF::IdentifyType(FileUtil::IOFile& file) {
|
||||||
return FileType::Error;
|
return FileType::Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus AppLoader_ELF::Load(Kernel::SharedPtr<Kernel::Process>& process) {
|
ResultStatus AppLoader_ELF::Load(std::shared_ptr<Kernel::Process>& process) {
|
||||||
if (is_loaded)
|
if (is_loaded)
|
||||||
return ResultStatus::ErrorAlreadyLoaded;
|
return ResultStatus::ErrorAlreadyLoaded;
|
||||||
|
|
||||||
|
@ -393,7 +393,7 @@ ResultStatus AppLoader_ELF::Load(Kernel::SharedPtr<Kernel::Process>& process) {
|
||||||
return ResultStatus::Error;
|
return ResultStatus::Error;
|
||||||
|
|
||||||
ElfReader elf_reader(&buffer[0]);
|
ElfReader elf_reader(&buffer[0]);
|
||||||
SharedPtr<CodeSet> codeset = elf_reader.LoadInto(Memory::PROCESS_IMAGE_VADDR);
|
std::shared_ptr<CodeSet> codeset = elf_reader.LoadInto(Memory::PROCESS_IMAGE_VADDR);
|
||||||
codeset->name = filename;
|
codeset->name = filename;
|
||||||
|
|
||||||
process = Core::System::GetInstance().Kernel().CreateProcess(std::move(codeset));
|
process = Core::System::GetInstance().Kernel().CreateProcess(std::move(codeset));
|
||||||
|
|
|
@ -30,7 +30,7 @@ public:
|
||||||
return IdentifyType(file);
|
return IdentifyType(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
|
ResultStatus Load(std::shared_ptr<Kernel::Process>& process) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string filename;
|
std::string filename;
|
||||||
|
|
|
@ -99,7 +99,7 @@ public:
|
||||||
* @param process The newly created process.
|
* @param process The newly created process.
|
||||||
* @return The status result of the operation.
|
* @return The status result of the operation.
|
||||||
*/
|
*/
|
||||||
virtual ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) = 0;
|
virtual ResultStatus Load(std::shared_ptr<Kernel::Process>& process) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the system mode that this application needs.
|
* Loads the system mode that this application needs.
|
||||||
|
|
|
@ -61,9 +61,9 @@ std::pair<std::optional<u32>, ResultStatus> AppLoader_NCCH::LoadKernelSystemMode
|
||||||
ResultStatus::Success);
|
ResultStatus::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus AppLoader_NCCH::LoadExec(Kernel::SharedPtr<Kernel::Process>& process) {
|
ResultStatus AppLoader_NCCH::LoadExec(std::shared_ptr<Kernel::Process>& process) {
|
||||||
using Kernel::CodeSet;
|
using Kernel::CodeSet;
|
||||||
using Kernel::SharedPtr;
|
using std::shared_ptr;
|
||||||
|
|
||||||
if (!is_loaded)
|
if (!is_loaded)
|
||||||
return ResultStatus::ErrorNotLoaded;
|
return ResultStatus::ErrorNotLoaded;
|
||||||
|
@ -75,7 +75,7 @@ ResultStatus AppLoader_NCCH::LoadExec(Kernel::SharedPtr<Kernel::Process>& proces
|
||||||
std::string process_name = Common::StringFromFixedZeroTerminatedBuffer(
|
std::string process_name = Common::StringFromFixedZeroTerminatedBuffer(
|
||||||
(const char*)overlay_ncch->exheader_header.codeset_info.name, 8);
|
(const char*)overlay_ncch->exheader_header.codeset_info.name, 8);
|
||||||
|
|
||||||
SharedPtr<CodeSet> codeset =
|
std::shared_ptr<CodeSet> codeset =
|
||||||
Core::System::GetInstance().Kernel().CreateCodeSet(process_name, program_id);
|
Core::System::GetInstance().Kernel().CreateCodeSet(process_name, program_id);
|
||||||
|
|
||||||
codeset->CodeSegment().offset = 0;
|
codeset->CodeSegment().offset = 0;
|
||||||
|
@ -151,7 +151,7 @@ void AppLoader_NCCH::ParseRegionLockoutInfo() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus AppLoader_NCCH::Load(Kernel::SharedPtr<Kernel::Process>& process) {
|
ResultStatus AppLoader_NCCH::Load(std::shared_ptr<Kernel::Process>& process) {
|
||||||
u64_le ncch_program_id;
|
u64_le ncch_program_id;
|
||||||
|
|
||||||
if (is_loaded)
|
if (is_loaded)
|
||||||
|
|
|
@ -33,7 +33,7 @@ public:
|
||||||
return IdentifyType(file);
|
return IdentifyType(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
|
ResultStatus Load(std::shared_ptr<Kernel::Process>& process) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the Exheader and returns the system mode for this application.
|
* Loads the Exheader and returns the system mode for this application.
|
||||||
|
@ -65,7 +65,7 @@ private:
|
||||||
* @param process The newly created process
|
* @param process The newly created process
|
||||||
* @return ResultStatus result of function
|
* @return ResultStatus result of function
|
||||||
*/
|
*/
|
||||||
ResultStatus LoadExec(Kernel::SharedPtr<Kernel::Process>& process);
|
ResultStatus LoadExec(std::shared_ptr<Kernel::Process>& process);
|
||||||
|
|
||||||
/// Reads the region lockout info in the SMDH and send it to CFG service
|
/// Reads the region lockout info in the SMDH and send it to CFG service
|
||||||
void ParseRegionLockoutInfo();
|
void ParseRegionLockoutInfo();
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
static SharedPtr<Object> MakeObject(Kernel::KernelSystem& kernel) {
|
static std::shared_ptr<Object> MakeObject(Kernel::KernelSystem& kernel) {
|
||||||
return kernel.CreateEvent(ResetType::OneShot);
|
return kernel.CreateEvent(ResetType::OneShot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
|
||||||
Core::Timing timing;
|
Core::Timing timing;
|
||||||
Memory::MemorySystem memory;
|
Memory::MemorySystem memory;
|
||||||
Kernel::KernelSystem kernel(memory, timing, [] {}, 0);
|
Kernel::KernelSystem kernel(memory, timing, [] {}, 0);
|
||||||
auto session = std::get<SharedPtr<ServerSession>>(kernel.CreateSessionPair());
|
auto session = std::get<std::shared_ptr<ServerSession>>(kernel.CreateSessionPair());
|
||||||
HLERequestContext context(kernel, std::move(session));
|
HLERequestContext context(kernel, std::move(session));
|
||||||
|
|
||||||
auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
|
auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
|
||||||
|
@ -236,7 +236,7 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
|
||||||
Core::Timing timing;
|
Core::Timing timing;
|
||||||
Memory::MemorySystem memory;
|
Memory::MemorySystem memory;
|
||||||
Kernel::KernelSystem kernel(memory, timing, [] {}, 0);
|
Kernel::KernelSystem kernel(memory, timing, [] {}, 0);
|
||||||
auto session = std::get<SharedPtr<ServerSession>>(kernel.CreateSessionPair());
|
auto session = std::get<std::shared_ptr<ServerSession>>(kernel.CreateSessionPair());
|
||||||
HLERequestContext context(kernel, std::move(session));
|
HLERequestContext context(kernel, std::move(session));
|
||||||
|
|
||||||
auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
|
auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
|
||||||
|
|
Loading…
Reference in a new issue