You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
160 lines
3.3 KiB
160 lines
3.3 KiB
#include "watchos.h"
|
|
#include "IRunnable.h"
|
|
|
|
struct KernelHandle
|
|
{
|
|
kernel_handle_t handle;
|
|
kernel_handle_destructor_t destructor;
|
|
void* object;
|
|
uint references;
|
|
uint32_t well_known = 0;
|
|
};
|
|
|
|
struct KernelTask
|
|
{
|
|
kernel_handle_t handle;
|
|
Task* task;
|
|
};
|
|
|
|
void destruct_task(kernel_handle_t handle, void* object)
|
|
{
|
|
delete object;
|
|
}
|
|
|
|
Kernel::Kernel()
|
|
{
|
|
for (int i = 0; i < KERNEL_MAX_HANDLES; i++)
|
|
{
|
|
m_handle[i] = nullptr;
|
|
}
|
|
|
|
for (int i = 0; i < KERNEL_MAX_TASKS; i++)
|
|
{
|
|
m_task[i] = nullptr;
|
|
}
|
|
}
|
|
|
|
kernel_handle_t Kernel::allocHandle(byte type, void* object, kernel_handle_destructor_t destructor, uint32_t well_known)
|
|
{
|
|
for (int i = 0; i < KERNEL_MAX_HANDLES; i++)
|
|
{
|
|
if (m_handle[i] == nullptr)
|
|
{
|
|
m_handle[i] = new KernelHandle();
|
|
m_handle[i]->handle = type | m_next_handle++;
|
|
m_handle[i]->destructor = destructor;
|
|
m_handle[i]->object = object;
|
|
m_handle[i]->references = 1;
|
|
m_handle[i]->well_known = well_known;
|
|
return m_handle[i]->handle;
|
|
}
|
|
}
|
|
watchos::panic("Exceeded KERNEL_MAX_HANDLES");
|
|
}
|
|
|
|
void Kernel::freeHandle(kernel_handle_t handle)
|
|
{
|
|
for (int i = 0; i < KERNEL_MAX_HANDLES; i++)
|
|
{
|
|
if (m_handle[i] != nullptr && m_handle[i]->handle == handle)
|
|
{
|
|
if (m_handle[i]->destructor != nullptr)
|
|
{
|
|
(m_handle[i]->destructor)(handle, m_handle[i]->object);
|
|
}
|
|
delete m_handle[i];
|
|
m_handle[i] = nullptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
void* Kernel::getHandle(kernel_handle_t handle)
|
|
{
|
|
for (int i = 0; i < KERNEL_MAX_HANDLES; i++)
|
|
{
|
|
if (m_handle[i] != nullptr && m_handle[i]->handle == handle)
|
|
{
|
|
m_handle[i]->references++;
|
|
return m_handle[i]->object;
|
|
}
|
|
}
|
|
watchos::panic("Attempt to access invalid Kernel handle");
|
|
}
|
|
|
|
void* Kernel::getHandle(uint32_t well_known)
|
|
{
|
|
for (int i = 0; i < KERNEL_MAX_HANDLES; i++)
|
|
{
|
|
if (m_handle[i] != nullptr && m_handle[i]->well_known == well_known)
|
|
{
|
|
m_handle[i]->references++;
|
|
return m_handle[i]->object;
|
|
}
|
|
}
|
|
watchos::panic("Attempt to access invalid Kernel handle by well-known id: %#10x", well_known);
|
|
}
|
|
|
|
void Kernel::releaseHandle(kernel_handle_t handle)
|
|
{
|
|
for (int i = 0; i < KERNEL_MAX_HANDLES; i++)
|
|
{
|
|
if (m_handle[i] != nullptr && m_handle[i]->handle == handle)
|
|
{
|
|
m_handle[i]->references--;
|
|
|
|
if (m_handle[i]->references == 0)
|
|
{
|
|
freeHandle(handle);
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
watchos::panic("Attempt to release invalid Kernel handle");
|
|
}
|
|
|
|
kernel_handle_t Kernel::registerTask(Task* task)
|
|
{
|
|
for (int i = 0; i < KERNEL_MAX_TASKS; i++)
|
|
{
|
|
if (m_task[i] == nullptr)
|
|
{
|
|
m_task[i] = new KernelTask();
|
|
m_task[i]->handle = allocHandle(WATCHOS_HANDLE_TYPE_TASK, (void*)destruct_task);
|
|
m_task[i]->task = task;
|
|
return m_task[i]->handle;
|
|
}
|
|
}
|
|
|
|
watchos::panic("Exceeded KERNEL_MAX_TASKS");
|
|
}
|
|
|
|
void Kernel::unregisterTask(Task* task)
|
|
{
|
|
for (int i = 0; i < KERNEL_MAX_TASKS; i++)
|
|
{
|
|
if (m_task[i] != nullptr && m_task[i]->task == task)
|
|
{
|
|
releaseHandle(m_task[i]->handle);
|
|
delete m_task[i];
|
|
m_task[i] = nullptr;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Kernel::tick()
|
|
{
|
|
for (int i = 0; i < KERNEL_MAX_TASKS; i++)
|
|
{
|
|
if (m_task[i] != nullptr)
|
|
{
|
|
IRunnable* runnable = dynamic_cast<IRunnable*>(m_task[i]->task);
|
|
if (runnable != nullptr)
|
|
{
|
|
runnable->tick();
|
|
}
|
|
}
|
|
}
|
|
}
|