概念

内核在处理中断请求时,要求在单位时间内可以处理尽可能多的中断,也就是系统要求处理中断的吞吐率要尽可能地大。这就要求中断处理程序要尽可能地短小精悍,并且不能有耗时操作。但是大多数的中断处理程序是很复杂的,很难在短时间内处理完毕。为了提高系统的响应能力和并发能力,需要解决平衡中断处理程序时间要求短和工作量要大的问题,SylixOS 将中断处理分为两个阶段,也就是顶半部和底半部:

  • 顶半部完成的一般是紧急的硬件操作,一般包括读取寄存器中的中断状态,清除中断标志,将底半部处理程序挂到底半部的执行队列中去;
  • 底半部完成大部分的耗时操作,并且可以被新的中断打断。

如果中断处理程序足够简单,则不需要分为顶半部和底半部,直接在顶半部完成即可。SylixOS 实现底半部的机制是中断延迟工作队列(InterDefer)。

接口

接口 说明
API_InterDeferGet 获得对应 CPU 的中断延迟队列
API_InterDeferContext 是否在中断延迟队列任务上下文
API_InterDeferJobAdd 向中断延迟处理队列加入任务
API_InterDeferJobDelete 从中断延迟处理队列删除任务

实现

中断延迟工作队列基于内核工作队列实现,同时创建优先级为0(最高优先级)的执行线程。对于多核处理器可以选择每个核有自己独立的工作队列,也可以和单核一样使用单一工作队列模式。

/*********************************************************************************************************
**
**                                    中国软件开源组织
**
**                                   嵌入式实时操作系统
**
**                                SylixOS(TM)  LW : long wing
**
**                               Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文   件   名: InterDefer.c
**
** 创   建   人: Han.Hui (韩辉)
**
** 文件创建日期: 2016 年 05 月 09 日
**
** 描        述: 中断延迟队列处理.
*********************************************************************************************************/
#define  __SYLIXOS_KERNEL
#include "../SylixOS/kernel/include/k_kernel.h"
/*********************************************************************************************************裁剪配置
*********************************************************************************************************/
#if LW_CFG_ISR_DEFER_EN > 0
/*********************************************************************************************************每一个 CPU 的 DEFER ISR QUEUE
*********************************************************************************************************/
#if (LW_CFG_SMP_EN > 0) && (LW_CFG_ISR_DEFER_PER_CPU > 0)
static LW_JOB_QUEUE     _K_jobqIsrDefer[LW_CFG_MAX_PROCESSORS];
static LW_JOB_MSG       _K_jobmsgIsrDefer[LW_CFG_MAX_PROCESSORS][LW_CFG_ISR_DEFER_SIZE];
#else
static LW_JOB_QUEUE     _K_jobqIsrDefer[1];
static LW_JOB_MSG       _K_jobmsgIsrDefer[LW_CFG_ISR_DEFER_SIZE];
#endif                                                                  /*  LW_CFG_SMP_EN > 0           */
/*********************************************************************************************************
** 函数名称: __interDeferTask
** 功能描述: 获得中断堆栈使用量
** 输 入  : ulCPUId                       CPU 号
**           pstFreeByteSize               空闲堆栈大小   (可为 LW_NULL)
**           pstUsedByteSize               使用堆栈大小   (可为 LW_NULL)
** 输 出  :
** 全局变量:
** 调用模块:
*********************************************************************************************************/
static PVOID  _interDeferTask (PVOID  pvArg)
{PLW_JOB_QUEUE   pjobq = (PLW_JOB_QUEUE)pvArg;for (;;) {_jobQueueExec(pjobq, LW_OPTION_WAIT_INFINITE);}return  (LW_NULL);
}
/*********************************************************************************************************
** 函数名称: _interDeferInit
** 功能描述: 初始化中断延迟处理
** 输 入  : NONE
** 输 出  : NONE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
VOID  _interDeferInit (VOID)
{CHAR                  cDefer[LW_CFG_OBJECT_NAME_SIZE] = "t_isrdefer";LW_CLASS_THREADATTR   threadattr;LW_OBJECT_HANDLE      ulId;#if (LW_CFG_SMP_EN > 0) && (LW_CFG_ISR_DEFER_PER_CPU > 0)INT                   i;LW_CLASS_CPUSET       cpuset;LW_CPU_ZERO(&cpuset);API_ThreadAttrBuild(&threadattr, LW_CFG_THREAD_DEFER_STK_SIZE, LW_CFG_ISR_DEFER_PRIO, (LW_OPTION_THREAD_STK_CHK | LW_OPTION_THREAD_SAFE | LW_OPTION_OBJECT_GLOBAL |LW_OPTION_THREAD_DETACHED |LW_OPTION_THREAD_AFFINITY_ALWAYS), LW_NULL);LW_CPU_FOREACH (i) {if (_jobQueueInit(&_K_jobqIsrDefer[i], &_K_jobmsgIsrDefer[i][0], LW_CFG_ISR_DEFER_SIZE, LW_FALSE)) {_DebugHandle(__ERRORMESSAGE_LEVEL, "can not create ISR defer queue.\r\n");return;}lib_itoa(i, &cDefer[10], 10);API_ThreadAttrSetArg(&threadattr, &_K_jobqIsrDefer[i]);ulId = API_ThreadInit(cDefer, _interDeferTask, &threadattr, LW_NULL);if (ulId == LW_OBJECT_HANDLE_INVALID) {_DebugHandle(__ERRORMESSAGE_LEVEL, "can not create ISR defer task.\r\n");return;}LW_CPU_SET(i, &cpuset);API_ThreadSetAffinity(ulId, sizeof(LW_CLASS_CPUSET), &cpuset);  /*  锁定到指定 CPU              */LW_CPU_CLR(i, &cpuset);API_ThreadStart(ulId);}#elseif (_jobQueueInit(&_K_jobqIsrDefer[0], &_K_jobmsgIsrDefer[0], LW_CFG_ISR_DEFER_SIZE, LW_FALSE)) {_DebugHandle(__ERRORMESSAGE_LEVEL, "can not create ISR defer queue.\r\n");return;}API_ThreadAttrBuild(&threadattr, LW_CFG_THREAD_DEFER_STK_SIZE, LW_CFG_ISR_DEFER_PRIO, (LW_OPTION_THREAD_STK_CHK | LW_OPTION_THREAD_SAFE | LW_OPTION_OBJECT_GLOBAL |LW_OPTION_THREAD_DETACHED |LW_OPTION_THREAD_AFFINITY_ALWAYS), &_K_jobqIsrDefer[0]);ulId = API_ThreadInit(cDefer, _interDeferTask, &threadattr, LW_NULL);if (ulId == LW_OBJECT_HANDLE_INVALID) {_DebugHandle(__ERRORMESSAGE_LEVEL, "can not create ISR defer task.\r\n");return;}API_ThreadStart(ulId);
#endif                                                                  /*  LW_CFG_SMP_EN > 0           */
}                                                                       /*  LW_CFG_ISR_DEFER_PER_CPU    */
/*********************************************************************************************************
** 函数名称: API_InterDeferGet
** 功能描述: 获得对应 CPU 的中断延迟队列
** 输 入  : ulCPUId       CPU 号
** 输 出  : 中断延迟队列
** 全局变量:
** 调用模块: API 函数
*********************************************************************************************************/
LW_API
PLW_JOB_QUEUE  API_InterDeferGet (ULONG  ulCPUId)
{if (ulCPUId >= LW_NCPUS) {_ErrorHandle(ERANGE);return  (LW_NULL);}#if (LW_CFG_SMP_EN > 0) && (LW_CFG_ISR_DEFER_PER_CPU > 0)return  (&_K_jobqIsrDefer[ulCPUId]);
#elsereturn  (&_K_jobqIsrDefer[0]);
#endif                                                                  /*  LW_CFG_SMP_EN > 0           */
}                                                                       /*  LW_CFG_ISR_DEFER_PER_CPU    */
/*********************************************************************************************************
** 函数名称: API_InterDeferJobAdd
** 功能描述: 向中断延迟处理队列加入一个任务
** 输 入  : pjobq         队列
**           pfunc         处理函数
**           pvArg         处理参数
** 输 出  : ERROR CODE
** 全局变量:
** 调用模块: API 函数
*********************************************************************************************************/
LW_API
ULONG  API_InterDeferJobAdd (PLW_JOB_QUEUE  pjobq, VOIDFUNCPTR  pfunc, PVOID  pvArg)
{if (!pjobq) {_ErrorHandle(EINVAL);return  (EINVAL);}return  (_jobQueueAdd(pjobq, pfunc, pvArg, LW_NULL, LW_NULL, LW_NULL, LW_NULL, LW_NULL));
}
/*********************************************************************************************************
** 函数名称: API_InterDeferJobDelete
** 功能描述: 从中断延迟处理队列删除任务
** 输 入  : pjobq         队列
**           bMatchArg     是否进行参数匹配判断
**           pfunc         处理函数
**           pvArg         处理参数
** 输 出  : NONE
** 全局变量:
** 调用模块: API 函数
*********************************************************************************************************/
LW_API
ULONG  API_InterDeferJobDelete (PLW_JOB_QUEUE  pjobq, BOOL  bMatchArg, VOIDFUNCPTR  pfunc, PVOID  pvArg)
{if (!pjobq) {_ErrorHandle(EINVAL);return  (EINVAL);}_jobQueueDel(pjobq, (bMatchArg) ? 1 : 0,pfunc, pvArg, LW_NULL, LW_NULL, LW_NULL, LW_NULL, LW_NULL);return  (ERROR_NONE);
}#endif                                                                  /*  LW_CFG_ISR_DEFER_EN > 0     */
/*********************************************************************************************************END
*********************************************************************************************************/

用法

下列代码展示了 SylixOS 中断底半部在驱动开发中的使用,内核模块设置某个 GPIO 的中断处理函数并使能中断,当产生对应的按键中断时,中断处理函数会清除中断,并将耗时操作插入到中断延迟队列中,卸载内核模块时清除该 GPIO 的相关设置并删除工作队列。

#define __SYLIXOS_STDIO
#define __SYLIXOS_KERNEL
#include <SylixOS.h>
#include <module.h>#define KEY_NUM 36PVOID _G_pvWorkQueue;
static INT _G_iIrqNum;static VOID __workHandler(PVOID  pvArg)
{printk("work handler function start.\n");API_TimeSSleep(5);printk("work handler function stop.\n");
}static irqreturn_t GpioIsr (INT iGpioNum, ULONG ulVector)
{API_GpioClearIrq(iGpioNum);API_InterDeferJobAdd(API_InterDeferGet(0), __workHandler, NULL);return (LW_IRQ_HANDLED);
}void module_init (void)
{INT iError;iError = API_GpioRequestOne(KEY_NUM, LW_GPIOF_IN, "KEY");if (iError != ERROR_NONE) {printk("failed to request gpio %d!\n", KEY_NUM);return;}_G_iIrqNum = API_GpioSetupIrq(KEY_NUM, LW_FALSE, 0);if (_G_iIrqNum == PX_ERROR) {printk("failed to setup gpio %d irq!\n", KEY_NUM);return;}iError = API_InterVectorConnect((ULONG)_G_iIrqNum,(PINT_SVR_ROUTINE)GpioIsr,(PVOID)KEY_NUM,"GpioIsr");if (iError != ERROR_NONE) {printk("failed to connect GpioIsr!\n");return;}API_InterVectorEnable(_G_iIrqNum);printk("interrupt_module init!\n");
}void module_exit (void)
{API_InterVectorDisconnect((ULONG)_G_iIrqNum,(PINT_SVR_ROUTINE)GpioIsr,(PVOID)KEY_NUM);API_GpioFree(KEY_NUM);printk("interrupt_module exit!\n");
}

在 SylixOS Shell 下装载模块,然后通过按下指定的按键触发中断:

#insmod ./interrupt.ko
interrupt_module init!
module interrupt.ko register ok, handle: 0x13338f0
work handler function start.
work handler function stop.

在 SylixOS Shell 下卸载模块:

#rmmod interrupt.ko
interrupt_module exit!
module /lib/modules/interrupt.ko unregister ok.

SylixOS中断延迟队列相关推荐

  1. JUC学习 - 延迟队列 DelayQueue 详解

    1.DelayQueue基本特征 public class DelayQueue<E extends Delayed> extends AbstractQueue<E>impl ...

  2. SpringBoot整合Redisson实现延迟队列

    SpringBoot整合Redisson实现延迟队列 技术选型 引入 Redisson 依赖 配置项 编写工具类 延迟队列执行器 业务消费类枚举 加载消费队列 消费者类 测试类 测试结果 技术选型 关 ...

  3. RabbitMQ实现延迟队列的方式

    1.背景 最近在做类似拍卖系统的上架功能,卖家上架物品以后,例如到期时间24小时或者48小时,如果无竞拍者或者购买者,则物品自动下架到用户的邮件中.诸如电商用户下单,30分钟未支付,则自动取消订单,归 ...

  4. (Interrupt Latency) 中断延迟

    中断延迟 (Interrupt Latency) 中断延迟 是指从硬件中断发生到开始执行中断处理程序第一条指令之间的这段时间. 也就是: 计算机接收到中断信号到操作系统作出响应,并完成换到转入中断服务 ...

  5. 消息延迟队列处理拼团时间到期

    1.RabbitMqConfig /*** * 延时队列交换机* * 注意这里的交换机类型:CustomExchange* ** * @return* */ @Bean public CustomEx ...

  6. 面试官:RabbitMQ本身不支持延迟队列,那你给我实现一个?

    以下文章来源方志朋的博客,回复"666"获面试宝典 RabbitMQ本身没有延迟队列的支持,但是基于其本身的一些特性,可以做到类似延迟队列的效果:基于死信交换器+TTL. 以下介绍 ...

  7. RabbitMQ 延迟队列实现定时任务的正确姿势,你学会了么?

    以下文章来源方志朋的博客,回复"666"获面试宝典 场景 开发中经常需要用到定时任务,对于商城来说,定时任务尤其多,比如优惠券定时过期.订单定时关闭.微信支付2小时未支付关闭订单等 ...

  8. RabbitMQ 延迟队列,太实用了!

    点击关注公众号,Java干货及时送达 目前常见的应用软件都有消息的延迟推送的影子,应用也极为广泛,例如: 淘宝七天自动确认收货.在我们签收商品后,物流系统会在七天后延时发送一个消息给支付系统,通知支付 ...

  9. rabbitmq利用死信队列+TTL 实现延迟队列

    2019独角兽企业重金招聘Python工程师标准>>> 适用场景:订单超时未支付,倘若适用定时器的话,那么数据量大的话,轮询查询数据,首先IO开销大,其次任务时间要求高,扫描越频繁性 ...

最新文章

  1. IT阅读——关于“业务”
  2. ubuntu10.0.4使用再生龙还原后在启动时不能正常启动
  3. JavaScript 弱类型
  4. The hierarchy of the type is inconsistent
  5. js字符串的字典序_27. 字符串的排列
  6. 微课|中学生可以这样学Python(例11.3):tkinter通信录管理系统1
  7. Ruby on Rails 实践
  8. 为你的.NET/Mono应用程序加入更新支持NetSparkle
  9. VM虚拟机Bridge模式VMnet0网卡无法启动问题的解决
  10. 开放、创新、合作,共赢多样性计算新时代
  11. 快速给pdf生成书签
  12. 阿里电话面试经过与总结
  13. 统计 fasta 文件序列长度及 GC 含量
  14. 面试 11、知识拓展
  15. Spring MVC ajax请求
  16. js利用点击事件更换皮肤
  17. IAR Systems
  18. dvt高危患者的护理措施_DVT的预防措施
  19. vue 移动端H5微信支付和支付宝支付
  20. 用 Python 爬了点你们喜欢的电影,这些电影真的很不错

热门文章

  1. 一个操作系统的实现(8)进程间通信
  2. iPhone 电池容量怎么算?
  3. PPT锁定了,不能编辑是什么原因
  4. 有5个学生,每个学生的数据包括学号、姓名、三门课的成绩,从键盘输入5个学生数据,要求打印出三门课总平均成绩,以及最高分的学生的数据(包括学号、姓名、三门课的成绩、平均分数)。VS2019版
  5. html5 自动矢量化,ArcScan自动矢量化
  6. 电路中滤波电容和退耦电容_电容在电路中究竟有多少种应用?
  7. 地域微信平台自媒体,原创视频如何插入腾讯地图
  8. 未知USB设备(设备描述符请求失败)终于解决。网上查到的所有方法我都试过了,全部失败。我的成功方法就是调整“电源选项”
  9. SLAM基础——李群李代数
  10. iOS中block的详解weakSelf、strongSelf-转自唐巧