Initial commit

This commit is contained in:
InoriRus
2021-12-01 19:29:27 +10:00
parent b1e7dcdc5d
commit 43f49c8763
1843 changed files with 1111694 additions and 0 deletions
+389
View File
@@ -0,0 +1,389 @@
#include "Emulator/Kernel/EventQueue.h"
#include "Kyty/Core/Common.h"
#include "Kyty/Core/DbgAssert.h"
#include "Kyty/Core/LinkList.h"
#include "Kyty/Core/String.h"
#include "Kyty/Core/Threads.h"
#include "Kyty/Core/Timer.h"
#include "Emulator/Libs/Errno.h"
#include "Emulator/Libs/Libs.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::LibKernel::EventQueue {
LIB_NAME("libkernel", "libkernel");
class KernelEqueuePrivate
{
public:
KernelEqueuePrivate() = default;
virtual ~KernelEqueuePrivate();
KYTY_CLASS_NO_COPY(KernelEqueuePrivate);
[[nodiscard]] const String& GetName() const { return m_name; }
void SetName(const String& m_name) { this->m_name = m_name; }
void AddEvent(const KernelEqueueEvent& event);
bool TriggerEvent(uintptr_t ident, int16_t filter, void* trigger_data);
bool DeleteEvent(uintptr_t ident, int16_t filter);
int GetTriggeredEvents(KernelEvent* ev, int num);
int WaitForEvents(KernelEvent* ev, int num, uint32_t micros);
private:
Core::List<KernelEqueueEvent> m_events;
Core::Mutex m_mutex;
Core::CondVar m_cond_var;
String m_name;
};
KernelEqueuePrivate::~KernelEqueuePrivate()
{
Core::LockGuard lock(m_mutex);
FOR_LIST(index, m_events)
{
auto& event = m_events[index];
if (event.filter.delete_func != nullptr)
{
event.filter.delete_func(&event);
}
}
}
int KernelEqueuePrivate::GetTriggeredEvents(KernelEvent* ev, int num)
{
Core::LockGuard lock(m_mutex);
EXIT_IF(num < 1);
int ret = 0;
FOR_LIST(index, m_events)
{
auto& event = m_events[index];
if (event.triggered)
{
ev[ret++] = event.event;
if (event.filter.reset_func != nullptr)
{
event.filter.reset_func(&event);
}
if (ret >= num)
{
break;
}
}
}
return ret;
}
int KernelEqueuePrivate::WaitForEvents(KernelEvent* ev, int num, uint32_t micros)
{
Core::LockGuard lock(m_mutex);
EXIT_IF(num < 1);
uint32_t elapsed = 0;
Core::Timer t;
t.Start();
for (;;)
{
int ret = GetTriggeredEvents(ev, num);
if (ret > 0 || (elapsed >= micros && micros != 0))
{
return ret;
}
if (micros == 0)
{
m_cond_var.Wait(&m_mutex);
} else
{
m_cond_var.WaitFor(&m_mutex, micros - elapsed);
}
elapsed = static_cast<uint32_t>(t.GetTimeS() * 1000000.0);
}
return 0;
}
void KernelEqueuePrivate::AddEvent(const KernelEqueueEvent& event)
{
Core::LockGuard lock(m_mutex);
if (auto index = m_events.Find(event.event.ident, event.event.filter,
[](auto e, auto ident, auto filter) { return e.event.ident == ident && e.event.filter == filter; });
m_events.IndexValid(index))
{
m_events[index] = event;
} else
{
m_events.Add(event);
}
if (event.triggered)
{
m_cond_var.Signal();
}
}
bool KernelEqueuePrivate::TriggerEvent(uintptr_t ident, int16_t filter, void* trigger_data)
{
Core::LockGuard lock(m_mutex);
if (auto index = m_events.Find(ident, filter,
[](auto e, auto ident, auto filter) { return e.event.ident == ident && e.event.filter == filter; });
m_events.IndexValid(index))
{
auto& event = m_events[index];
if (event.filter.trigger_func != nullptr)
{
event.filter.trigger_func(&event, trigger_data);
} else
{
event.triggered = true;
}
m_cond_var.Signal();
return true;
}
return false;
}
bool KernelEqueuePrivate::DeleteEvent(uintptr_t ident, int16_t filter)
{
Core::LockGuard lock(m_mutex);
if (auto index = m_events.Find(ident, filter,
[](auto e, auto ident, auto filter) { return e.event.ident == ident && e.event.filter == filter; });
m_events.IndexValid(index))
{
auto& event = m_events[index];
if (event.filter.delete_func != nullptr)
{
event.filter.delete_func(&event);
}
m_events.Remove(index);
return true;
}
return false;
}
int KYTY_SYSV_ABI KernelCreateEqueue(KernelEqueue* eq, const char* name)
{
PRINT_NAME();
if (eq == nullptr || name == nullptr)
{
return KERNEL_ERROR_EINVAL;
}
*eq = new KernelEqueuePrivate;
(*eq)->SetName(String::FromUtf8(name));
printf("\tEqueue create: %s\n", name);
return OK;
}
int KYTY_SYSV_ABI KernelAddEvent(KernelEqueue eq, const KernelEqueueEvent& event)
{
if (eq == nullptr)
{
return KERNEL_ERROR_EBADF;
}
eq->AddEvent(event);
return OK;
}
int KYTY_SYSV_ABI KernelTriggerEvent(KernelEqueue eq, uintptr_t ident, int16_t filter, void* trigger_data)
{
if (eq == nullptr)
{
return KERNEL_ERROR_EBADF;
}
if (!eq->TriggerEvent(ident, filter, trigger_data))
{
return KERNEL_ERROR_ENOENT;
}
return OK;
}
int KYTY_SYSV_ABI KernelDeleteEvent(KernelEqueue eq, uintptr_t ident, int16_t filter)
{
if (eq == nullptr)
{
return KERNEL_ERROR_EBADF;
}
if (!eq->DeleteEvent(ident, filter))
{
return KERNEL_ERROR_ENOENT;
}
return OK;
}
int KYTY_SYSV_ABI KernelDeleteEqueue(KernelEqueue eq)
{
PRINT_NAME();
if (eq == nullptr)
{
return KERNEL_ERROR_EBADF;
}
printf("\tEqueue delete: %s\n", eq->GetName().C_Str());
delete eq;
return OK;
}
int KYTY_SYSV_ABI KernelWaitEqueue(KernelEqueue eq, KernelEvent* ev, int num, int* out, const KernelUseconds* timo)
{
PRINT_NAME();
if (eq == nullptr)
{
return KERNEL_ERROR_EBADF;
}
if (ev == nullptr)
{
return KERNEL_ERROR_EFAULT;
}
if (num < 1)
{
return KERNEL_ERROR_EINVAL;
}
EXIT_NOT_IMPLEMENTED(out == nullptr);
printf("\tEqueue wait: %s\n", eq->GetName().C_Str());
if (timo == nullptr)
{
*out = eq->WaitForEvents(ev, num, 0);
}
if (timo != nullptr)
{
if (*timo == 0)
{
*out = eq->GetTriggeredEvents(ev, num);
} else
{
*out = eq->WaitForEvents(ev, num, *timo);
}
}
if (*out == 0)
{
printf("\ttimedout\n");
return KERNEL_ERROR_ETIMEDOUT;
}
printf("\treceived %u events\n", *out);
return OK;
}
intptr_t KYTY_SYSV_ABI KernelGetEventData(const KernelEvent* ev)
{
PRINT_NAME();
if (ev != nullptr)
{
return ev->data;
}
return 0;
}
intptr_t KYTY_SYSV_ABI KernelGetEventFflags(const KernelEvent* ev)
{
PRINT_NAME();
if (ev != nullptr)
{
return ev->fflags;
}
return 0;
}
int KYTY_SYSV_ABI KernelGetEventFilter(const KernelEvent* ev)
{
PRINT_NAME();
if (ev != nullptr)
{
return ev->filter;
}
return 0;
}
uintptr_t KYTY_SYSV_ABI KernelGetEventId(const KernelEvent* ev)
{
PRINT_NAME();
if (ev != nullptr)
{
return ev->ident;
}
return 0;
}
void* KYTY_SYSV_ABI KernelGetEventUserData(const KernelEvent* ev)
{
PRINT_NAME();
if (ev != nullptr)
{
return ev->udata;
}
return nullptr;
}
int KYTY_SYSV_ABI KernelGetEventError(const KernelEvent* /*ev*/)
{
PRINT_NAME();
KYTY_NOT_IMPLEMENTED;
return 0;
}
} // namespace Kyty::Libs::LibKernel::EventQueue
#endif // KYTY_EMU_ENABLED