mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-05-24 03:36:52 -04:00
kern: implement SvcWaitSynchronization
This commit is contained in:
parent
16c9c53a4a
commit
f52232f0f2
10 changed files with 211 additions and 59 deletions
|
@ -211,6 +211,49 @@ namespace ams::kern {
|
|||
static_assert(std::is_base_of<KAutoObject, T>::value);
|
||||
return this->Register(handle, obj, obj->GetTypeObj().GetClassToken());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ALWAYS_INLINE bool GetMultipleObjects(T **out, const ams::svc::Handle *handles, size_t num_handles) const {
|
||||
/* Try to convert and open all the handles. */
|
||||
size_t num_opened;
|
||||
{
|
||||
/* Lock the table. */
|
||||
KScopedDisableDispatch dd;
|
||||
KScopedSpinLock lk(this->lock);
|
||||
for (num_opened = 0; num_opened < num_handles; num_opened++) {
|
||||
/* Get the current handle. */
|
||||
const auto cur_handle = handles[num_opened];
|
||||
|
||||
/* Get the object for the current handle. */
|
||||
KAutoObject *cur_object = this->GetObjectImpl(cur_handle);
|
||||
if (AMS_UNLIKELY(cur_object == nullptr)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Cast the current object to the desired type. */
|
||||
T *cur_t = cur_object->DynamicCast<T*>();
|
||||
if (AMS_UNLIKELY(cur_t == nullptr)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Open a reference to the current object. */
|
||||
cur_t->Open();
|
||||
out[num_opened] = cur_t;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we converted every object, succeed. */
|
||||
if (AMS_LIKELY(num_opened == num_handles)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If we didn't convert entry object, close the ones we opened. */
|
||||
for (size_t i = 0; i < num_opened; i++) {
|
||||
out[i]->Close();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
private:
|
||||
NOINLINE Result Add(ams::svc::Handle *out_handle, KAutoObject *obj, u16 type);
|
||||
NOINLINE void Register(ams::svc::Handle handle, KAutoObject *obj, u16 type);
|
||||
|
@ -318,49 +361,6 @@ namespace ams::kern {
|
|||
*out_handle = EncodeHandle(index, entry->GetLinearId());
|
||||
return entry->GetObject();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ALWAYS_INLINE bool GetMultipleObjects(T **out, const ams::svc::Handle *handles, size_t num_handles) const {
|
||||
/* Try to convert and open all the handles. */
|
||||
size_t num_opened;
|
||||
{
|
||||
/* Lock the table. */
|
||||
KScopedDisableDispatch dd;
|
||||
KScopedSpinLock lk(this->lock);
|
||||
for (num_opened = 0; num_opened < num_handles; num_opened++) {
|
||||
/* Get the current handle. */
|
||||
const auto cur_handle = handles[num_opened];
|
||||
|
||||
/* Get the object for the current handle. */
|
||||
KAutoObject *cur_object = this->GetObjectImpl(cur_handle);
|
||||
if (AMS_UNLIKELY(cur_object == nullptr)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Cast the current object to the desired type. */
|
||||
T *cur_t = cur_object->DynamicCast<T*>();
|
||||
if (AMS_UNLIKELY(cur_t == nullptr)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Open a reference to the current object. */
|
||||
cur_t->Open();
|
||||
out[num_opened] = cur_t;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we converted every object, succeed. */
|
||||
if (AMS_LIKELY(num_opened == num_handles)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If we didn't convert entry object, close the ones we opened. */
|
||||
for (size_t i = 0; i < num_opened; i++) {
|
||||
out[i]->Close();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -42,8 +42,8 @@ namespace ams::kern {
|
|||
virtual bool IsSignaled() const = 0;
|
||||
virtual void DebugWaiters();
|
||||
|
||||
iterator AddWaiterThread(KThread *thread);
|
||||
iterator RemoveWaiterThread(iterator it);
|
||||
iterator RegisterWaitingThread(KThread *thread);
|
||||
iterator UnregisterWaitingThread(iterator it);
|
||||
|
||||
iterator begin();
|
||||
iterator end();
|
||||
|
|
|
@ -113,8 +113,8 @@ namespace ams::kern {
|
|||
private:
|
||||
static constexpr size_t PriorityInheritanceCountMax = 10;
|
||||
union SyncObjectBuffer {
|
||||
KSynchronizationObject *sync_objects[ams::svc::MaxWaitSynchronizationHandleCount];
|
||||
ams::svc::Handle handles[ams::svc::MaxWaitSynchronizationHandleCount * (sizeof(KSynchronizationObject *) / sizeof(ams::svc::Handle))];
|
||||
KSynchronizationObject *sync_objects[ams::svc::ArgumentHandleCountMax];
|
||||
ams::svc::Handle handles[ams::svc::ArgumentHandleCountMax * (sizeof(KSynchronizationObject *) / sizeof(ams::svc::Handle))];
|
||||
|
||||
constexpr SyncObjectBuffer() : sync_objects() { /* ... */ }
|
||||
};
|
||||
|
@ -310,10 +310,25 @@ namespace ams::kern {
|
|||
constexpr KThread *GetLockOwner() const { return this->lock_owner; }
|
||||
|
||||
constexpr void SetSyncedObject(KSynchronizationObject *obj, Result wait_res) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
this->synced_object = obj;
|
||||
this->wait_result = wait_res;
|
||||
}
|
||||
|
||||
constexpr Result GetWaitResult(KSynchronizationObject **out) const {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
*out = this->synced_object;
|
||||
return this->wait_result;
|
||||
}
|
||||
|
||||
bool IsWaitCancelled() const { return this->wait_cancelled; }
|
||||
void ClearWaitCancelled() { this->wait_cancelled = false; }
|
||||
|
||||
void ClearCancellable() { this->cancellable = false; }
|
||||
void SetCancellable() { this->cancellable = true; }
|
||||
|
||||
bool HasWaiters() const { return !this->waiter_list.empty(); }
|
||||
|
||||
constexpr s64 GetLastScheduledTick() const { return this->last_scheduled_tick; }
|
||||
|
@ -325,6 +340,9 @@ namespace ams::kern {
|
|||
constexpr KProcessAddress GetThreadLocalRegionAddress() const { return this->tls_address; }
|
||||
constexpr void *GetThreadLocalRegionHeapAddress() const { return this->tls_heap_address; }
|
||||
|
||||
constexpr KSynchronizationObject **GetSynchronizationObjectBuffer() { return std::addressof(this->sync_object_buffer.sync_objects[0]); }
|
||||
constexpr ams::svc::Handle *GetHandleBuffer() { return std::addressof(this->sync_object_buffer.handles[sizeof(this->sync_object_buffer.sync_objects) / sizeof(ams::svc::Handle) - ams::svc::ArgumentHandleCountMax]); }
|
||||
|
||||
constexpr u16 GetUserPreemptionState() const { return *GetPointer<u16>(this->tls_address + 0x100); }
|
||||
constexpr void SetKernelPreemptionState(u16 state) const { *GetPointer<u16>(this->tls_address + 0x100 + sizeof(u16)) = state; }
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue