定义

/** low level task data that entry.S needs immediate access to.* __switch_to() assumes cpu_context follows immediately after cpu_domain.*/
struct thread_info {unsigned long       flags;      /* low level flags */mm_segment_t       addr_limit; /* address limit */struct task_struct   *task;      /* main task structure */struct exec_domain *exec_domain;   /* execution domain */struct restart_block  restart_block;int           preempt_count;  /* 0 => preemptable, <0 => bug */int         cpu;        /* cpu */
};

在支持可抢占的系统中,一个进程的therad_info信息定义如上。其中preempt_count代表的是该进程是否可以被抢占,根据注释的说明当peermpt_count等于0的时候当前进程就可以被抢占,当小于0存在bug,当不等于0也就是大于0说明当前进程不可以被抢占。不可抢占的原因很多,比如当前进程在中断上下文中或者使用了锁(spin_lock的过程中会disable掉抢占的)。至于当前是什么原因不能被抢占,就需要看peermpt_count每个字段的含义。

字段含义

先来看如下图所示的各个字段的含义
再来看看代码中关于preempt_count的各个字段的定义:
<linux/include/preempt_mask.h>
------------------------------------------
/** We put the hardirq and softirq counter into the preemption* counter. The bitmask has the following meaning:** - bits 0-7 are the preemption count (max preemption depth: 256)* - bits 8-15 are the softirq count (max # of softirqs: 256)** The hardirq count could in theory be the same as the number of* interrupts in the system, but we run all interrupt handlers with* interrupts disabled, so we cannot have nesting interrupts. Though* there are a few palaeontologic drivers which reenable interrupts in* the handler, so we need more than one bit here.** PREEMPT_MASK:   0x000000ff* SOFTIRQ_MASK:   0x0000ff00* HARDIRQ_MASK:   0x000f0000*     NMI_MASK:   0x00100000* PREEMPT_ACTIVE: 0x00200000*/
#define PREEMPT_BITS    8
#define SOFTIRQ_BITS    8
#define HARDIRQ_BITS    4
#define NMI_BITS    1

结合上述的示图和代码的定义可知,bit0-7代表的是抢占的次数,最大抢占深度为256次; bit8-15代表的是软中断的次数,最大也是256次; bit16-19表示硬件中断的次数,注释的大概意思是避免中断嵌套,但是也不能防止某些驱动中嵌套使用中断,所以嵌套16层也是最大次数了。bit20代表NMI中断,bit21代表当前抢占是否active。

相关宏定义

linux系统为了方便得出各个字段的值,提供了一系列宏定义如下:
#define PREEMPT_SHIFT   0
#define SOFTIRQ_SHIFT   (PREEMPT_SHIFT + PREEMPT_BITS)                        //0+8=8
#define HARDIRQ_SHIFT   (SOFTIRQ_SHIFT + SOFTIRQ_BITS)                        //8+8=16
#define NMI_SHIFT   (HARDIRQ_SHIFT + HARDIRQ_BITS)                        //16+4=20#define __IRQ_MASK(x) ((1UL << (x))-1)#define PREEMPT_MASK  (__IRQ_MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
#define SOFTIRQ_MASK    (__IRQ_MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
#define HARDIRQ_MASK    (__IRQ_MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
#define NMI_MASK    (__IRQ_MASK(NMI_BITS)     << NMI_SHIFT)#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT)                //1<<0
#define SOFTIRQ_OFFSET  (1UL << SOFTIRQ_SHIFT)                //1<<8
#define HARDIRQ_OFFSET  (1UL << HARDIRQ_SHIFT)                //1<<16
#define NMI_OFFSET  (1UL << NMI_SHIFT)                    //1<<20#define SOFTIRQ_DISABLE_OFFSET (2 * SOFTIRQ_OFFSET)           //16#define PREEMPT_ACTIVE_BITS  1
#define PREEMPT_ACTIVE_SHIFT    (NMI_SHIFT + NMI_BITS)
#define PREEMPT_ACTIVE  (__IRQ_MASK(PREEMPT_ACTIVE_BITS) << PREEMPT_ACTIVE_SHIFT)#define hardirq_count()  (preempt_count() & HARDIRQ_MASK)                                     //硬中断count
#define softirq_count() (preempt_count() & SOFTIRQ_MASK)                                     //软中断count
#define irq_count() (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK \| NMI_MASK))                                                  //所有中断=硬+软+NMI

从上述的定义可以得出,如果想知道硬中断的次数就使用hardirq_count, 如果想知道软中断次数就使用softirq_count, 如果想知道所有中断的次数就使用irq_count。

各种上下文

/** Are we doing bottom half or hardware interrupt processing?* Are we in a softirq context? Interrupt context?* in_softirq - Are we currently processing softirq or have bh disabled?* in_serving_softirq - Are we currently processing softirq?*/
#define in_irq()        (hardirq_count())
#define in_softirq()        (softirq_count())
#define in_interrupt()      (irq_count())
#define in_serving_softirq()    (softirq_count() & SOFTIRQ_OFFSET)

其中in_irq用于判断当前进程是否在硬中断中;  in_softirq用于判断是否当前进程在软件中断或者有别的进程disable了软中断

in_interrupt用于判断当前进程是否在中断中; 而in_serving_softirq用于判断当前进程是否在软件中断中,通过bit8这一位来判断。
#define in_atomic()  ((preempt_count() & ~PREEMPT_ACTIVE) != 0)

使用上述的宏判断当前进程是否处于原子操作中。

preempt_count相关推荐

  1. preempt_count详解

    当从内核态返回到用户态的时候,要检查是否进行调度,而调度要看两个条件: 1.preempt_count是否为0 2.rescheduled是否置位 ret_from_exception:  preem ...

  2. preempt_count分析

    kernel通过preempt_count变量来判断是否处于中断(soft/hard/nmi)上下文,是否可以抢占,先看示例 #define in_irq() (hardirq_count()) #d ...

  3. Kernel: x86: preempt_count, per-cpu(每个CPU一份的变量)

    文章目录 源码位置 preempt_count 使用的地方 saved_preempt_count 源码位置 arch/x86/include/asm/preempt.h 在include/asm-g ...

  4. [Linux内核]软中断与硬中断

    转自:http://blog.csdn.net/zhangskd/article/details/21992933 本文主要内容:硬中断 / 软中断的原理和实现 内核版本:2.6.37 Author: ...

  5. Linux内核跟踪之trace框架分析【转】

    转自:http://blog.chinaunix.net/uid-20543183-id-1930846.html ------------------------------------------ ...

  6. Linux进程管理 (7)实时调度

    关键词:RT.preempt_count.RT patch. 除了CFS调度器之外,还包括重要的实时调度器,有两种RR和FIFO调度策略.本章只是一个简单的介绍. 更详细的介绍参考<Linux进 ...

  7. 使用 ftrace 调试 Linux 内核【转】

    转自:http://blog.csdn.net/adaptiver/article/details/7930646 使用 ftrace 调试 Linux 内核,第 1 部分 http://blog.c ...

  8. 关于might_sleep的一点说明【转】

    转自:http://blog.csdn.net/chen_chuang_/article/details/48462575 这个函数我在看代码时基本上是直接忽略的(因为我知道它实际上不干什么事),不过 ...

  9. linux --- 进程调度

    2019独角兽企业重金招聘Python工程师标准>>> Linux进程调度笔记 一:Linux进程的四大要素 1:一段供进程执行的程序,该程序可以被多个进程执行. 2:独立的内核堆栈 ...

  10. Linux内核抢占实现机制分析【转】

    Linux内核抢占实现机制分析 转自:http://blog.chinaunix.net/uid-24227137-id-3050754.html [摘要]本文详解了Linux内核抢占实现机制.首先介 ...

最新文章

  1. 蓝牙模块与电脑无线通信--AD测量大电压
  2. 语音基础知识-基本语音知识,声谱图,log梅普图,MFCC,deltas详解
  3. 转载:Pixhawk源码笔记七:姿态控制预览
  4. 【mysql安装】阿里云centos7环境mysql安装
  5. Win10设置防火墙,使局域网能访问此电脑的Tomcat服务
  6. python带我起飞 百度云_CentOS/Debian安装人人影视客户端,下载资源并自动上传到OneDrive网盘...
  7. Java的throws Exception
  8. 产品经理职场面试35个经典问题
  9. 2008最火爆的十大网络流行语
  10. 编程比赛三大赛制介绍(ACM赛制、OI赛制、IOI赛制)
  11. VSCode格式化JS自动添加或去掉分号
  12. python学习笔记——语法基础
  13. 网络 随笔 1-再补充一丢丢常识
  14. 知乎高赞的7个顶级资源网站,记住了帮你减少一半的搜索时间
  15. WinEdt Latex 在字母上加两个点
  16. 最高补贴1000元/kW,山东光伏补贴来了
  17. 追源索骥:透过源码看懂Flink核心框架的执行流程--来自GitHub
  18. 【web渗透思路】框架敏感信息泄露(特点、目录、配置)
  19. XXX测试用例设计?XXX怎么测试?(行李箱、电梯、水杯、笔、椅子)
  20. java源码模拟面试解析指南,快手支付中台java面试题

热门文章

  1. mybatis实现延迟加载多对一
  2. Redis常见配置文件详解
  3. 词法分析(1)...
  4. 20145307第二次JAVA学习实验报告
  5. Kafka 几个实现细节
  6. Elasticsearch从0.90(0.90.x)到1.2(1.x)API的变化-二
  7. 深度学习基础系列(六)| 权重初始化的选择
  8. 人人都能懂的Vue源码系列—08—initLifecycle
  9. linq where的应用
  10. 中国互联网今日正式满 20 岁