1、概述
内核工作队列(JobQueue)位于内核文件libsylixos/SylixOS/kernel/core/_JobQueue.c
中,是纯粹的针对工作队列对象的一些操作集合,供内核使用,系统工作队列和网络工作队列都是基于内核工作队列实现的。
内核工作队列本质上是基于数组型环形缓冲区实现的,同时使用了自旋锁进行过程保护和使用了信号量进行资源同步。实现过程比较简单,可以看源码直接分析。
2、相关数据结构
SylixOS内核中定义了两个用于管理工作队列的数据结构。
2.1、工作队列管理的消息
typedef struct {
VOIDFUNCPTR JOBM_pfuncFunc;
PVOID JOBM_pvArg[LW_JOB_ARGS];
} LW_JOB_MSG;
- JOBM_pfuncFunc:工作消息的回调函数;
- JOBM_pvArg[LW_JOB_ARGS]:工作消息的回调函数的参数。
2.2、工作队列控制块
typedef struct {
PLW_JOB_MSG JOBQ_pjobmsgQueue;
UINT JOBQ_uiIn;
UINT JOBQ_uiOut;
UINT JOBQ_uiCnt;
UINT JOBQ_uiSize;
size_t JOBQ_stLost;
LW_OBJECT_HANDLE JOBQ_ulSync;
LW_SPINLOCK_DEFINE (JOBQ_slLock);
} LW_JOB_QUEUE;
- JOBQ_pjobmsgQueue:工作队列消息;
- JOBQ_uiIn:加入工作队列的消息数量;
- JOBQ_uiOut:移出工作队列的消息数量;
- JOBQ_uiCnt:当前工作队列中的消息数量;
- JOBQ_uiSize:工作队列总大小;
- JOBQ_stLost:工作队列丢失消息数量;
- JOBQ_ulSync:工作队列同步等待信号;
- JOBQ_slLock:锁定工作队列自旋锁。
3、相关接口函数
3.1 创建及删除工作队列
SylixOS中创建工作队列就是分配工作队列资源和初始化工作队列控制块中各成员的过程,与之对应,删除队列就是释放工作队列资源的过程。内核中提供了两种工作队列的创建和删除操作函数:动态/静态创建和删除工作队列。
_JobQueueCreate
原型 : PLW_JOB_QUEUE _jobQueueCreate (UINT uiQueueSize, BOOL bNonBlock)
输入 : uiQueueSize 队列大小
bNonBlock 执行函数是否为非阻塞方式
返回 : 工作队列控制块
说明 : 创建一个工作队列(动态创建)
_JobQueueDelete
原型 : VOID _jobQueueDelete (PLW_JOB_QUEUE pjobq)
输入 : pjobq 工作队列控制块
返回 : NONE
说明 : 删除一个工作队列(动态创建)
_JobQueueInit
原型 : ULONG _jobQueueInit (PLW_JOB_QUEUE pjobq,
PLW_JOB_MSG pjobmsg,
UINT uiQueueSize,
BOOL bNonBlock)
输入 : pjobq 需要初始化的工作队列控制块
pjobmsg 消息缓冲区
uiQueueSize 队列大小
bNonBlock 执行函数是否为非阻塞方式
返回 : 工作队列控制块
说明 : 初始化一个工作队列 (静态创建)
_jobQueueFinit
原型 : VOID _jobQueueFinit (PLW_JOB_QUEUE pjobq)
输入 : pjobq 工作队列控制块
返回 : NONE
说明 : 销毁一个工作队列 (静态销毁)
3.2 清空工作队列
清空工作队列的操作就是将指定工作队列控制块中的同步等待信号量清除,同时将工作队列的入队计数、出队计数和当前工作队列中消息数全部清零。
_jobQueueFlush
原型 : VOID _jobQueueFlush (PLW_JOB_QUEUE pjobq)
输入 : pjobq 工作队列控制块
返回 : NONE
说明 : 清空工作队列
3.3 添加工作
向一个工作队列中添加一个工作就是将一个工作消息保存到工作队列的消息管理成员,同时将该工作需要执行的回调函数及其参数保存到消息控制块中。
_JobQueueAdd
原型 : ULONG _jobQueueAdd (PLW_JOB_QUEUE pjobq,
输入 : pjobq 工作队列控制块
pfunc 要执行的函数
pvArg0 ~ 5 函数参数
返回 : ERROR
说明 : 添加一个工作到工作队列
3.4 删除工作
删除工作队列中某一工作就是遍历工作队列消息列表,根据函数名及其参数个数匹配,将该工作的回调函数置空。
_JobQueueDel
原型 : VOID _jobQueueDel (PLW_JOB_QUEUE pjobq,
输入 : pjobq 工作队列控制块
uiMatchArgNum 匹配参数的个数
pfunc 要删除的函数
pvArg0 ~ 5 函数参数
返回 : NONE
说明 : 从工作队列中删除一个工作 (懒惰删除)
3.5 获得丢失消息数量
当工作队列控制块中当前消息数量JOBQ_uiCnt等于工作队列总大小JOBQ_uiSize时,若此时又要向该工作队列中添加新的工作消息,则该工作消息会丢失并且丢失消息数量JOBQ_stLost将会加1,因此获取工作队列控制块的JOBQ_stLost的值即可获得当前丢失的消息数量。
_jobQueueLost
原型 : ULONG _jobQueueLost (PLW_JOB_QUEUE pjobq)
输入 : pjobq 工作队列控制块
返回 : NONE
说明 : 获得工作队列丢失信息数量
3.6 执行工作
调用_jobQueueExec即可执行工作队列中的工作,其详细描述如下:
_jobQueueExec
原型 : ULONG _jobQueueExec (PLW_JOB_QUEUE pjobq, ULONG ulTimeout)
输入 : pjobq 工作队列控制块
ulTimeout 等待超时时间
返回 : 不为 ERROR_NONE 表示超时
说明 : 执行工作队列中的工作
执行工作队列中的工作就是判断工作队列中是否存在工作消息,若存在,则依次执行工作消息的回调函数,直至工作队列中的消息数量减为0。执行工作的具体流程如图 3.1所示。
4、 程序源码
/*********************************************************************************************************
**
** 中国软件开源组织
**
** 嵌入式实时操作系统
**
** SylixOS(TM) LW : long wing
**
** Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文 件 名: _JobQueue.c
**
** 创 建 人: Han.Hui (韩辉)
**
** 文件创建日期: 2013 年 12 月 01 日
**
** 描 述: 这是系统异步工作队列.
**
** BUG:
2018.01.05 _jobQueueDel() 如果 pfunc 参数为 NULL 则表示任意函数.
*********************************************************************************************************/
#define __SYLIXOS_KERNEL
#include "../SylixOS/kernel/include/k_kernel.h"
/*********************************************************************************************************
JOB MSG COPY
*********************************************************************************************************/
#define LW_JOB_MSG_COPY(t, f) \
{ \
(t)->JOBM_pfuncFunc = (f)->JOBM_pfuncFunc; \
(t)->JOBM_pvArg[0] = (f)->JOBM_pvArg[0]; \
(t)->JOBM_pvArg[1] = (f)->JOBM_pvArg[1]; \
(t)->JOBM_pvArg[2] = (f)->JOBM_pvArg[2]; \
(t)->JOBM_pvArg[3] = (f)->JOBM_pvArg[3]; \
(t)->JOBM_pvArg[4] = (f)->JOBM_pvArg[4]; \
(t)->JOBM_pvArg[5] = (f)->JOBM_pvArg[5]; \
}
/*********************************************************************************************************
** 函数名称: _JobQueueCreate
** 功能描述: 创建一个工作队列
** 输 入 : uiQueueSize 队列大小
** bNonBlock 执行函数是否为非阻塞方式
** 输 出 : 工作队列控制块
** 全局变量:
** 调用模块:
*********************************************************************************************************/
PLW_JOB_QUEUE _jobQueueCreate (UINT uiQueueSize, BOOL bNonBlock)
{
PLW_JOB_QUEUE pjobq;
pjobq = (PLW_JOB_QUEUE)__KHEAP_ALLOC((size_t)(sizeof(LW_JOB_QUEUE) +
(uiQueueSize * sizeof(LW_JOB_MSG))));
if (pjobq == LW_NULL) {
_DebugHandle(__ERRORMESSAGE_LEVEL, "kernel low memory.\r\n");
_ErrorHandle(ERROR_KERNEL_LOW_MEMORY);
return (LW_NULL);
}
pjobq->JOBQ_pjobmsgQueue = (PLW_JOB_MSG)(pjobq + 1);
pjobq->JOBQ_uiIn = 0;
pjobq->JOBQ_uiOut = 0;
pjobq->JOBQ_uiCnt = 0;
pjobq->JOBQ_uiSize = uiQueueSize;
pjobq->JOBQ_ulLost = 0;
if (bNonBlock == LW_FALSE) {
pjobq->JOBQ_ulSync = API_SemaphoreBCreate("job_sync", LW_FALSE, LW_OPTION_OBJECT_GLOBAL, LW_NULL);
if (pjobq->JOBQ_ulSync == LW_OBJECT_HANDLE_INVALID) {
__KHEAP_FREE(pjobq);
return (LW_NULL);
}
} else {
pjobq->JOBQ_ulSync = LW_OBJECT_HANDLE_INVALID;
}
LW_SPIN_INIT(&pjobq->JOBQ_slLock);
return (pjobq);
}
/*********************************************************************************************************
** 函数名称: _JobQueueDelete
** 功能描述: 删除一个工作队列
** 输 入 : pjobq 工作队列控制块
** 输 出 : NONE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
VOID _jobQueueDelete (PLW_JOB_QUEUE pjobq)
{
if (pjobq->JOBQ_ulSync) {
API_SemaphoreBDelete(&pjobq->JOBQ_ulSync);
}
__KHEAP_FREE(pjobq);
}
/*********************************************************************************************************
** 函数名称: _JobQueueInit
** 功能描述: 初始化一个工作队列 (静态创建)
** 输 入 : pjobq 需要初始化的工作队列控制块
** pjobmsg 消息缓冲区
** uiQueueSize 队列大小
** bNonBlock 执行函数是否为非阻塞方式
** 输 出 : 工作队列控制块
** 全局变量:
** 调用模块:
*********************************************************************************************************/
ULONG _jobQueueInit (PLW_JOB_QUEUE pjobq, PLW_JOB_MSG pjobmsg, UINT uiQueueSize, BOOL bNonBlock)
{
pjobq->JOBQ_pjobmsgQueue = pjobmsg;
pjobq->JOBQ_uiIn = 0;
pjobq->JOBQ_uiOut = 0;
pjobq->JOBQ_uiCnt = 0;
pjobq->JOBQ_uiSize = uiQueueSize;
pjobq->JOBQ_ulLost = 0;
if (bNonBlock == LW_FALSE) {
pjobq->JOBQ_ulSync = API_SemaphoreBCreate("job_sync", LW_FALSE, LW_OPTION_OBJECT_GLOBAL, LW_NULL);
if (pjobq->JOBQ_ulSync == LW_OBJECT_HANDLE_INVALID) {
return (errno);
}
}
LW_SPIN_INIT(&pjobq->JOBQ_slLock);
return (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: _jobQueueFinit
** 功能描述: 销毁一个工作队列 (静态销毁)
** 输 入 : pjobq 工作队列控制块
** 输 出 : NONE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
VOID _jobQueueFinit (PLW_JOB_QUEUE pjobq)
{
if (pjobq->JOBQ_ulSync) {
API_SemaphoreBDelete(&pjobq->JOBQ_ulSync);
}
}
/*********************************************************************************************************
** 函数名称: _jobQueueFlush
** 功能描述: 清空工作队列
** 输 入 : pjobq 工作队列控制块
** 输 出 : NONE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
VOID _jobQueueFlush (PLW_JOB_QUEUE pjobq)
{
INTREG iregInterLevel;
if (pjobq->JOBQ_ulSync) {
API_SemaphoreBClear(pjobq->JOBQ_ulSync);
}
LW_SPIN_LOCK_QUICK(&pjobq->JOBQ_slLock, &iregInterLevel);
pjobq->JOBQ_uiIn = 0;
pjobq->JOBQ_uiOut = 0;
pjobq->JOBQ_uiCnt = 0;
LW_SPIN_UNLOCK_QUICK(&pjobq->JOBQ_slLock, iregInterLevel);
}
/*********************************************************************************************************
** 函数名称: _JobQueueAdd
** 功能描述: 添加一个工作到工作队列
** 输 入 : pjobq 工作队列控制块
** pfunc 要执行的函数
** pvArg0 ~ 5 函数参数
** 输 出 : ERROR
** 全局变量:
** 调用模块:
*********************************************************************************************************/
ULONG _jobQueueAdd (PLW_JOB_QUEUE pjobq,
VOIDFUNCPTR pfunc,
PVOID pvArg0,
PVOID pvArg1,
PVOID pvArg2,
PVOID pvArg3,
PVOID pvArg4,
PVOID pvArg5)
{
INTREG iregInterLevel;
PLW_JOB_MSG pjobmsg;
LW_SPIN_LOCK_QUICK(&pjobq->JOBQ_slLock, &iregInterLevel);
if (pjobq->JOBQ_uiCnt == pjobq->JOBQ_uiSize) {
pjobq->JOBQ_ulLost++;
LW_SPIN_UNLOCK_QUICK(&pjobq->JOBQ_slLock, iregInterLevel);
_DebugHandle(__ERRORMESSAGE_LEVEL, "job message lost.\r\n");
return (ENOSPC);
}
pjobmsg = &pjobq->JOBQ_pjobmsgQueue[pjobq->JOBQ_uiIn];
pjobmsg->JOBM_pfuncFunc = pfunc;
pjobmsg->JOBM_pvArg[0] = pvArg0;
pjobmsg->JOBM_pvArg[1] = pvArg1;
pjobmsg->JOBM_pvArg[2] = pvArg2;
pjobmsg->JOBM_pvArg[3] = pvArg3;
pjobmsg->JOBM_pvArg[4] = pvArg4;
pjobmsg->JOBM_pvArg[5] = pvArg5;
if (pjobq->JOBQ_uiIn == (pjobq->JOBQ_uiSize - 1)) {
pjobq->JOBQ_uiIn = 0;
} else {
pjobq->JOBQ_uiIn++;
}
pjobq->JOBQ_uiCnt++;
LW_SPIN_UNLOCK_QUICK(&pjobq->JOBQ_slLock, iregInterLevel);
if (pjobq->JOBQ_ulSync) {
API_SemaphoreBPost(pjobq->JOBQ_ulSync);
}
return (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: _JobQueueDel
** 功能描述: 从工作队列中删除一个工作 (懒惰删除)
** 输 入 : pjobq 工作队列控制块
** uiMatchArgNum 匹配参数的个数
** pfunc 要删除的函数
** pvArg0 ~ 5 函数参数
** 输 出 : NONE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
VOID _jobQueueDel (PLW_JOB_QUEUE pjobq,
UINT uiMatchArgNum,
VOIDFUNCPTR pfunc,
PVOID pvArg0,
PVOID pvArg1,
PVOID pvArg2,
PVOID pvArg3,
PVOID pvArg4,
PVOID pvArg5)
{
INTREG iregInterLevel;
UINT i = 0;
PLW_JOB_MSG pjobmsg;
LW_SPIN_LOCK_QUICK(&pjobq->JOBQ_slLock, &iregInterLevel);
pjobmsg = &pjobq->JOBQ_pjobmsgQueue[pjobq->JOBQ_uiOut];
for (i = 0; i < pjobq->JOBQ_uiCnt; i++) {
switch (uiMatchArgNum) {
case 0:
if (pjobmsg->JOBM_pfuncFunc == pfunc || !pfunc) {
pjobmsg->JOBM_pfuncFunc = LW_NULL;
}
break;
case 1:
if ((pjobmsg->JOBM_pfuncFunc == pfunc || !pfunc) &&
(pjobmsg->JOBM_pvArg[0] == pvArg0)) {
pjobmsg->JOBM_pfuncFunc = LW_NULL;
}
break;
case 2:
if ((pjobmsg->JOBM_pfuncFunc == pfunc || !pfunc) &&
(pjobmsg->JOBM_pvArg[0] == pvArg0) &&
(pjobmsg->JOBM_pvArg[1] == pvArg1)) {
pjobmsg->JOBM_pfuncFunc = LW_NULL;
}
break;
case 3:
if ((pjobmsg->JOBM_pfuncFunc == pfunc || !pfunc) &&
(pjobmsg->JOBM_pvArg[0] == pvArg0) &&
(pjobmsg->JOBM_pvArg[1] == pvArg1) &&
(pjobmsg->JOBM_pvArg[2] == pvArg2)) {
pjobmsg->JOBM_pfuncFunc = LW_NULL;
}
break;
case 4:
if ((pjobmsg->JOBM_pfuncFunc == pfunc || !pfunc) &&
(pjobmsg->JOBM_pvArg[0] == pvArg0) &&
(pjobmsg->JOBM_pvArg[1] == pvArg1) &&
(pjobmsg->JOBM_pvArg[2] == pvArg2) &&
(pjobmsg->JOBM_pvArg[3] == pvArg3)) {
pjobmsg->JOBM_pfuncFunc = LW_NULL;
}
break;
case 5:
if ((pjobmsg->JOBM_pfuncFunc == pfunc || !pfunc) &&
(pjobmsg->JOBM_pvArg[0] == pvArg0) &&
(pjobmsg->JOBM_pvArg[1] == pvArg1) &&
(pjobmsg->JOBM_pvArg[2] == pvArg2) &&
(pjobmsg->JOBM_pvArg[3] == pvArg3) &&
(pjobmsg->JOBM_pvArg[4] == pvArg4)) {
pjobmsg->JOBM_pfuncFunc = LW_NULL;
}
break;
case 6:
if ((pjobmsg->JOBM_pfuncFunc == pfunc || !pfunc) &&
(pjobmsg->JOBM_pvArg[0] == pvArg0) &&
(pjobmsg->JOBM_pvArg[1] == pvArg1) &&
(pjobmsg->JOBM_pvArg[2] == pvArg2) &&
(pjobmsg->JOBM_pvArg[3] == pvArg3) &&
(pjobmsg->JOBM_pvArg[4] == pvArg4) &&
(pjobmsg->JOBM_pvArg[5] == pvArg5)) {
pjobmsg->JOBM_pfuncFunc = LW_NULL;
}
break;
}
pjobmsg++;
if (pjobmsg > &pjobq->JOBQ_pjobmsgQueue[pjobq->JOBQ_uiSize - 1]) {
pjobmsg = &pjobq->JOBQ_pjobmsgQueue[0];
}
}
LW_SPIN_UNLOCK_QUICK(&pjobq->JOBQ_slLock, iregInterLevel);
}
/*********************************************************************************************************
** 函数名称: _jobQueueLost
** 功能描述: 获得工作队列丢失信息数量
** 输 入 : pjobq 工作队列控制块
** 输 出 : NONE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
ULONG _jobQueueLost (PLW_JOB_QUEUE pjobq)
{
return (pjobq->JOBQ_ulLost);
}
/*********************************************************************************************************
** 函数名称: _jobQueueExec
** 功能描述: 执行工作队列中的工作
** 输 入 : pjobq 工作队列控制块
** ulTimeout 等待超时时间
** 输 出 : 不为 ERROR_NONE 表示超时
** 全局变量:
** 调用模块:
*********************************************************************************************************/
ULONG _jobQueueExec (PLW_JOB_QUEUE pjobq, ULONG ulTimeout)
{
INTREG iregInterLevel;
PLW_JOB_MSG pjobmsg;
LW_JOB_MSG jobmsgRun;
if (pjobq->JOBQ_ulSync) {
for (;;) {
if (API_SemaphoreBPend(pjobq->JOBQ_ulSync, ulTimeout)) {
return (ERROR_THREAD_WAIT_TIMEOUT);
}
LW_SPIN_LOCK_QUICK(&pjobq->JOBQ_slLock, &iregInterLevel);
if (pjobq->JOBQ_uiCnt) {
break;
}
LW_SPIN_UNLOCK_QUICK(&pjobq->JOBQ_slLock, iregInterLevel);
}
} else {
LW_SPIN_LOCK_QUICK(&pjobq->JOBQ_slLock, &iregInterLevel);
}
while (pjobq->JOBQ_uiCnt) {
pjobmsg = &pjobq->JOBQ_pjobmsgQueue[pjobq->JOBQ_uiOut];
LW_JOB_MSG_COPY(&jobmsgRun, pjobmsg);
if (pjobq->JOBQ_uiOut == (pjobq->JOBQ_uiSize - 1)) {
pjobq->JOBQ_uiOut = 0;
} else {
pjobq->JOBQ_uiOut++;
}
pjobq->JOBQ_uiCnt--;
LW_SPIN_UNLOCK_QUICK(&pjobq->JOBQ_slLock, iregInterLevel);
if (jobmsgRun.JOBM_pfuncFunc) {
jobmsgRun.JOBM_pfuncFunc(jobmsgRun.JOBM_pvArg[0],
jobmsgRun.JOBM_pvArg[1],
jobmsgRun.JOBM_pvArg[2],
jobmsgRun.JOBM_pvArg[3],
jobmsgRun.JOBM_pvArg[4],
jobmsgRun.JOBM_pvArg[5]);
}
LW_SPIN_LOCK_QUICK(&pjobq->JOBQ_slLock, &iregInterLevel);
}
LW_SPIN_UNLOCK_QUICK(&pjobq->JOBQ_slLock, iregInterLevel);
return (ERROR_NONE);
}
/*********************************************************************************************************
END
*********************************************************************************************************/