platform for developing on SQFMI's Watchy
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

#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();
}
}
}
}