2022-04-23 10:59:50 +02:00
|
|
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2020-12-22 07:36:53 +01:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
2021-04-04 04:11:46 +02:00
|
|
|
#include "core/hle/kernel/k_auto_object.h"
|
2020-12-22 07:36:53 +01:00
|
|
|
#include "core/hle/result.h"
|
|
|
|
|
|
|
|
namespace Kernel {
|
|
|
|
|
|
|
|
class KernelCore;
|
|
|
|
class Synchronization;
|
2020-12-31 08:01:08 +01:00
|
|
|
class KThread;
|
2020-12-22 07:36:53 +01:00
|
|
|
|
|
|
|
/// Class that represents a Kernel object that a thread can be waiting on
|
2021-04-04 04:11:46 +02:00
|
|
|
class KSynchronizationObject : public KAutoObjectWithList {
|
|
|
|
KERNEL_AUTOOBJECT_TRAITS(KSynchronizationObject, KAutoObject);
|
|
|
|
|
2020-12-22 07:36:53 +01:00
|
|
|
public:
|
|
|
|
struct ThreadListNode {
|
|
|
|
ThreadListNode* next{};
|
2020-12-31 08:01:08 +01:00
|
|
|
KThread* thread{};
|
2020-12-22 07:36:53 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
[[nodiscard]] static ResultCode Wait(KernelCore& kernel, s32* out_index,
|
|
|
|
KSynchronizationObject** objects, const s32 num_objects,
|
|
|
|
s64 timeout);
|
|
|
|
|
2021-05-29 08:49:07 +02:00
|
|
|
void Finalize() override;
|
2021-04-04 04:11:46 +02:00
|
|
|
|
2020-12-22 07:36:53 +01:00
|
|
|
[[nodiscard]] virtual bool IsSignaled() const = 0;
|
|
|
|
|
2020-12-31 08:01:08 +01:00
|
|
|
[[nodiscard]] std::vector<KThread*> GetWaitingThreadsForDebugging() const;
|
2020-12-22 07:36:53 +01:00
|
|
|
|
2021-11-21 11:30:16 +01:00
|
|
|
void LinkNode(ThreadListNode* node_) {
|
2021-11-10 04:02:11 +01:00
|
|
|
// Link the node to the list.
|
|
|
|
if (thread_list_tail == nullptr) {
|
2021-11-21 11:30:16 +01:00
|
|
|
thread_list_head = node_;
|
2021-11-10 04:02:11 +01:00
|
|
|
} else {
|
2021-11-21 11:30:16 +01:00
|
|
|
thread_list_tail->next = node_;
|
2021-11-10 04:02:11 +01:00
|
|
|
}
|
|
|
|
|
2021-11-21 11:30:16 +01:00
|
|
|
thread_list_tail = node_;
|
2021-11-10 04:02:11 +01:00
|
|
|
}
|
|
|
|
|
2021-11-21 11:30:16 +01:00
|
|
|
void UnlinkNode(ThreadListNode* node_) {
|
2021-11-10 04:02:11 +01:00
|
|
|
// Unlink the node from the list.
|
|
|
|
ThreadListNode* prev_ptr =
|
|
|
|
reinterpret_cast<ThreadListNode*>(std::addressof(thread_list_head));
|
|
|
|
ThreadListNode* prev_val = nullptr;
|
|
|
|
ThreadListNode *prev, *tail_prev;
|
|
|
|
|
|
|
|
do {
|
|
|
|
prev = prev_ptr;
|
|
|
|
prev_ptr = prev_ptr->next;
|
|
|
|
tail_prev = prev_val;
|
|
|
|
prev_val = prev_ptr;
|
2021-11-21 11:30:16 +01:00
|
|
|
} while (prev_ptr != node_);
|
2021-11-10 04:02:11 +01:00
|
|
|
|
2021-11-21 11:30:16 +01:00
|
|
|
if (thread_list_tail == node_) {
|
2021-11-10 04:02:11 +01:00
|
|
|
thread_list_tail = tail_prev;
|
|
|
|
}
|
|
|
|
|
2021-11-21 11:30:16 +01:00
|
|
|
prev->next = node_->next;
|
2021-11-10 04:02:11 +01:00
|
|
|
}
|
|
|
|
|
2020-12-22 07:36:53 +01:00
|
|
|
protected:
|
|
|
|
explicit KSynchronizationObject(KernelCore& kernel);
|
2021-05-29 08:49:07 +02:00
|
|
|
~KSynchronizationObject() override;
|
2020-12-22 07:36:53 +01:00
|
|
|
|
2021-04-04 04:11:46 +02:00
|
|
|
virtual void OnFinalizeSynchronizationObject() {}
|
|
|
|
|
2020-12-22 07:36:53 +01:00
|
|
|
void NotifyAvailable(ResultCode result);
|
|
|
|
void NotifyAvailable() {
|
2021-05-21 07:05:04 +02:00
|
|
|
return this->NotifyAvailable(ResultSuccess);
|
2020-12-22 07:36:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
ThreadListNode* thread_list_head{};
|
|
|
|
ThreadListNode* thread_list_tail{};
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace Kernel
|