SylixOS 内核工作队列

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
*********************************************************************************************************/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ScilogyHunter

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值