mirror of
https://gitee.com/Lamdonn/varch.git
synced 2025-12-07 01:06:41 +08:00
158 lines
4.0 KiB
C
158 lines
4.0 KiB
C
/*********************************************************************************************************
|
|
* ------------------------------------------------------------------------------------------------------
|
|
* file description
|
|
* ------------------------------------------------------------------------------------------------------
|
|
* \file kern.h
|
|
* \unit kern
|
|
* \brief This is a simple timing task scheduling kernel module for C language
|
|
* \author Lamdonn
|
|
* \version v1.0.0
|
|
* \license GPL-2.0
|
|
* \copyright Copyright (C) 2023 Lamdonn.
|
|
********************************************************************************************************/
|
|
#include "kern.h"
|
|
#include <stdlib.h>
|
|
|
|
/* task control block */
|
|
typedef struct
|
|
{
|
|
task_t task; /* task id, unique, natural number */
|
|
unsigned short period; /* task run cycle */
|
|
unsigned short ctime; /* task countdown */
|
|
task_handler_t handler; /* task callback function */
|
|
} TCB, *tcb_t;
|
|
|
|
/* task list */
|
|
typedef struct TASK_LIST
|
|
{
|
|
struct TASK_LIST *next; /* next task */
|
|
tcb_t tcb; /* task control block */
|
|
} TASK_LIST, *task_list_t;
|
|
|
|
/* kern manager */
|
|
typedef struct
|
|
{
|
|
task_list_t base; /* next task */
|
|
kern_tick_t tick_func; /* task control block */
|
|
unsigned int tick;
|
|
unsigned short time_slice;
|
|
task_t running;
|
|
} KERN_MANAGE;
|
|
|
|
static KERN_MANAGE manager;
|
|
|
|
int kern_init(kern_tick_t tick_func, unsigned short time_slice)
|
|
{
|
|
if (!tick_func) return KE_TASK_INVALID;
|
|
manager.tick_func = tick_func;
|
|
manager.time_slice = time_slice;
|
|
manager.base = NULL;
|
|
manager.tick = 0;
|
|
manager.running = 0;
|
|
return KE_OK;
|
|
}
|
|
|
|
task_t task_create(unsigned short period, task_handler_t handler)
|
|
{
|
|
task_t task = 1;
|
|
task_list_t node = NULL, prev = NULL;
|
|
|
|
if (!handler) return 0;
|
|
|
|
/* alloc task id */
|
|
node = manager.base;
|
|
while (node)
|
|
{
|
|
if (task < node->tcb->task) break;
|
|
else task = node->tcb->task + 1;
|
|
|
|
prev = node;
|
|
node = node->next;
|
|
}
|
|
|
|
/* allocate task control block space */
|
|
node = (task_list_t)malloc(sizeof(TASK_LIST));
|
|
if (!node) return 0;
|
|
node->tcb = (tcb_t)malloc(sizeof(TCB));
|
|
if (!node->tcb) { free(node); return 0; }
|
|
node->next = NULL;
|
|
|
|
if (!prev) manager.base = node;
|
|
else
|
|
{
|
|
node->next = prev->next;
|
|
prev->next = node;
|
|
}
|
|
|
|
node->tcb->task = task;
|
|
node->tcb->period = period;
|
|
node->tcb->ctime = 0;
|
|
node->tcb->handler = handler;
|
|
|
|
return task;
|
|
}
|
|
|
|
int task_delete(task_t task)
|
|
{
|
|
task_list_t node = NULL, prev = NULL;
|
|
|
|
if (task == 0) return KE_TASK_ID_ERR;
|
|
|
|
node = manager.base;
|
|
while (node)
|
|
{
|
|
if (node->tcb->task >= task) break;
|
|
prev = node;
|
|
node = node->next;
|
|
}
|
|
if (!node || task != node->tcb->task) return KE_TASK_ID_ERR;
|
|
|
|
if (!prev) manager.base = node->next;
|
|
else prev->next = node->next;
|
|
|
|
free(node->tcb);
|
|
free(node);
|
|
|
|
return KE_OK;
|
|
}
|
|
|
|
task_t task_running(void)
|
|
{
|
|
return manager.running;
|
|
}
|
|
|
|
void kern_schedule(void)
|
|
{
|
|
task_list_t l;
|
|
unsigned int t = manager.tick_func();
|
|
|
|
while (1)
|
|
{
|
|
l = manager.base;
|
|
t = manager.tick_func();
|
|
t = t < manager.tick ? ((int)manager.tick + t) : (t - manager.tick);
|
|
|
|
if (t)
|
|
{
|
|
while (l)
|
|
{
|
|
l->tcb->ctime += t;
|
|
if (l->tcb->ctime > l->tcb->period)
|
|
{
|
|
if (l->tcb->handler)
|
|
{
|
|
manager.running = l->tcb->task;
|
|
l->tcb->handler();
|
|
manager.running = 0;
|
|
}
|
|
l->tcb->ctime = 0;
|
|
}
|
|
|
|
l = l->next;
|
|
}
|
|
|
|
manager.tick = manager.tick_func();
|
|
}
|
|
}
|
|
}
|