1 Star 0 Fork 3

xc13AK/rhino

forked from AliOS Things/rhino 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
k_workqueue.c 7.46 KB
一键复制 编辑 原始数据 按行查看 历史
skylarCai 提交于 2021-05-10 17:09 . init version
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include "k_api.h"
#if (RHINO_CONFIG_WORKQUEUE > 0)
static kstat_t workqueue_is_exist(kworkqueue_t *workqueue)
{
CPSR_ALLOC();
kworkqueue_t *pos;
RHINO_CRITICAL_ENTER();
for (pos = krhino_list_entry(g_workqueue_list_head.next, kworkqueue_t, workqueue_node);
&pos->workqueue_node != &g_workqueue_list_head;
pos = krhino_list_entry(pos->workqueue_node.next, kworkqueue_t, workqueue_node)) {
if (pos == workqueue) {
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_EXIST;
}
}
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_NOT_EXIST;
}
static void worker_task(void *arg)
{
CPSR_ALLOC();
kstat_t ret;
kwork_t *work = NULL;
kworkqueue_t *queue = (kworkqueue_t *)arg;
while (1) {
ret = krhino_sem_take(&(queue->sem), RHINO_WAIT_FOREVER);
if (ret != RHINO_SUCCESS) {
k_err_proc(ret);
}
RHINO_CRITICAL_ENTER();
/* have work to do. */
work = krhino_list_entry(queue->work_list.next, kwork_t, work_node);
klist_rm_init(&(work->work_node));
queue->work_current = work;
work->work_exit = 0;
RHINO_CRITICAL_EXIT();
/* do work */
work->handle(work->arg);
RHINO_CRITICAL_ENTER();
/* clean current work */
queue->work_current = NULL;
RHINO_CRITICAL_EXIT();
}
}
kstat_t krhino_workqueue_create(kworkqueue_t *workqueue, const name_t *name,
uint8_t pri, cpu_stack_t *stack_buf, size_t stack_size)
{
CPSR_ALLOC();
kstat_t ret;
NULL_PARA_CHK(workqueue);
NULL_PARA_CHK(name);
NULL_PARA_CHK(stack_buf);
if (pri >= RHINO_CONFIG_PRI_MAX) {
return RHINO_BEYOND_MAX_PRI;
}
if (stack_size == 0u) {
return RHINO_TASK_INV_STACK_SIZE;
}
ret = workqueue_is_exist(workqueue);
if (ret == RHINO_WORKQUEUE_EXIST) {
return RHINO_WORKQUEUE_EXIST;
}
klist_init(&(workqueue->workqueue_node));
klist_init(&(workqueue->work_list));
workqueue->work_current = NULL;
workqueue->name = name;
ret = krhino_sem_create(&(workqueue->sem), "WORKQUEUE-SEM", 0);
if (ret != RHINO_SUCCESS) {
return ret;
}
RHINO_CRITICAL_ENTER();
klist_insert(&g_workqueue_list_head, &(workqueue->workqueue_node));
RHINO_CRITICAL_EXIT();
ret = krhino_task_create(&(workqueue->worker), name, (void *)workqueue, pri,
0, stack_buf, stack_size, worker_task, 1);
if (ret != RHINO_SUCCESS) {
RHINO_CRITICAL_ENTER();
klist_rm_init(&(workqueue->workqueue_node));
RHINO_CRITICAL_EXIT();
krhino_sem_del(&(workqueue->sem));
return ret;
}
TRACE_WORKQUEUE_CREATE(krhino_cur_task_get(), workqueue);
return RHINO_SUCCESS;
}
kstat_t krhino_workqueue_del(kworkqueue_t *workqueue)
{
CPSR_ALLOC();
kstat_t ret;
NULL_PARA_CHK(workqueue);
ret = workqueue_is_exist(workqueue);
if (ret == RHINO_WORKQUEUE_NOT_EXIST) {
return RHINO_WORKQUEUE_NOT_EXIST;
}
RHINO_CRITICAL_ENTER();
if (!is_klist_empty(&(workqueue->work_list))) {
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_BUSY;
}
if (workqueue->work_current != NULL) {
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_BUSY;
}
RHINO_CRITICAL_EXIT();
ret = krhino_task_del(&(workqueue->worker));
if (ret != RHINO_SUCCESS) {
return ret;
}
ret = krhino_sem_del(&(workqueue->sem));
if (ret != RHINO_SUCCESS) {
return ret;
}
RHINO_CRITICAL_ENTER();
klist_rm_init(&(workqueue->workqueue_node));
TRACE_WORKQUEUE_DEL(g_active_task[cpu_cur_get()], workqueue);
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
static void work_timer_cb(void *timer, void *arg)
{
CPSR_ALLOC();
kstat_t ret;
kwork_t *work = ((ktimer_t *)timer)->priv;
kworkqueue_t *wq = (kworkqueue_t *)arg;
RHINO_CRITICAL_ENTER();
if (wq->work_current == work) {
RHINO_CRITICAL_EXIT();
return;
}
if (work->work_exit == 1) {
RHINO_CRITICAL_EXIT();
return;
}
/* NOTE: the work MUST be initialized firstly */
klist_rm_init(&(work->work_node));
klist_insert(&(wq->work_list), &(work->work_node));
work->wq = wq;
work->work_exit = 1;
RHINO_CRITICAL_EXIT();
ret = krhino_sem_give(&(wq->sem));
if (ret != RHINO_SUCCESS) {
return;
}
}
kstat_t krhino_work_init(kwork_t *work, work_handle_t handle, void *arg,
tick_t dly)
{
kstat_t ret;
if (work == NULL) {
return RHINO_NULL_PTR;
}
if (handle == NULL) {
return RHINO_NULL_PTR;
}
NULL_PARA_CHK(work);
NULL_PARA_CHK(handle);
memset(work, 0, sizeof(kwork_t));
klist_init(&(work->work_node));
work->handle = handle;
work->arg = arg;
work->dly = dly;
work->wq = NULL;
if (dly > 0) {
ret = krhino_timer_dyn_create((ktimer_t **)(&work->timer), "WORK-TIMER", work_timer_cb,
work->dly, 0, (void *)work, 0);
if (ret != RHINO_SUCCESS) {
return ret;
}
}
TRACE_WORK_INIT(krhino_cur_task_get(), work);
return RHINO_SUCCESS;
}
kstat_t krhino_work_run(kworkqueue_t *workqueue, kwork_t *work)
{
CPSR_ALLOC();
kstat_t ret;
NULL_PARA_CHK(workqueue);
NULL_PARA_CHK(work);
RHINO_CRITICAL_ENTER();
if (work->dly == 0) {
if (workqueue->work_current == work) {
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_WORK_RUNNING;
}
if (work->work_exit == 1) {
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_WORK_EXIST;
}
/* NOTE: the work MUST be initialized firstly */
klist_rm_init(&(work->work_node));
klist_insert(&(workqueue->work_list), &(work->work_node));
work->wq = workqueue;
work->work_exit = 1;
RHINO_CRITICAL_EXIT();
ret = krhino_sem_give(&(workqueue->sem));
if (ret != RHINO_SUCCESS) {
return ret;
}
} else {
work->timer->priv = work;
RHINO_CRITICAL_EXIT();
ret = krhino_timer_arg_change_auto(work->timer, (void *)workqueue);
if (ret != RHINO_SUCCESS) {
return ret;
}
}
return RHINO_SUCCESS;
}
kstat_t krhino_work_sched(kwork_t *work)
{
return krhino_work_run(&g_workqueue_default, work);
}
kstat_t krhino_work_cancel(kwork_t *work)
{
CPSR_ALLOC();
kworkqueue_t *wq;
NULL_PARA_CHK(work);
wq = (kworkqueue_t *)work->wq;
if (wq == NULL) {
if (work->dly > 0) {
krhino_timer_stop(work->timer);
}
return RHINO_SUCCESS;
}
RHINO_CRITICAL_ENTER();
if (wq->work_current == work) {
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_WORK_RUNNING;
}
if (work->work_exit == 1) {
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_WORK_EXIST;
}
klist_rm_init(&(work->work_node));
work->wq = NULL;
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
void workqueue_init(void)
{
klist_init(&g_workqueue_list_head);
krhino_workqueue_create(&g_workqueue_default, "DEFAULT-WORKQUEUE",
RHINO_CONFIG_WORKQUEUE_TASK_PRIO, g_workqueue_stack,
RHINO_CONFIG_WORKQUEUE_STACK_SIZE);
}
#endif
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/xc13AK/rhino.git
git@gitee.com:xc13AK/rhino.git
xc13AK
rhino
rhino
master

搜索帮助