最近看各种上下文,发现和ThreadInfo中的preemption字段密切,于是便调查了下。

看下Linux源码中的注释:

/*
* 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 can in theory reach the same as NR_IRQS.
* In reality, the number of nested IRQS is limited to the stack
* size as well. For archs with over 1000 IRQS it is not practical
* to expect that they will all nest. We give a max of 10 bits for
* hardirq nesting. An arch may choose to give less than 10 bits.
* m68k expects it to be 8.
*
* - bits 16-25 are the hardirq count (max # of nested hardirqs: 1024)
* - bit 26 is the NMI_MASK
* - bit 27 is the PREEMPT_ACTIVE flag
*
* PREEMPT_MASK: 0x000000ff
* SOFTIRQ_MASK: 0x0000ff00
* HARDIRQ_MASK: 0x03ff0000
* NMI_MASK: 0x04000000
*/

这里其实把preempt_count划分成了四部分:抢占计数器、软中断计数、硬件中断计数、NMI计数。

抢占计数器:0-7位

软中断计数器:8-15位

硬中断计数器:16-25位

NMI标识:26位

基于上面的信息,看下Linux内核中判断各个上下文的宏:

#define hardirq_count()    (preempt_count() & HARDIRQ_MASK)
#define softirq_count() (preempt_count() & SOFTIRQ_MASK)
#define irq_count() (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK | NMI_MASK))

可以看到这里判断硬件中断/软中断/中断上下文的实质,就是根据thread_info结构中的preempt_count字段,额忘记列出preempt_count()的实现了:#define preempt_count() (current_thread_info()->preempt_count),这时明白了吧!!!

不过后面几个掩码的计算有点绕,参考下源码:

#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)

实质上就是取对应的位。

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

而这里只是对上面各种计数的包装,只要对应的计数不为0,则表示在对应的上下文中。in_interrupt表示中断上下文,包括了硬件中断、软中断和NMI中断。in_serving_softirq判断是否当前正在处理软中断。

#define in_nmi()    (preempt_count() & NMI_MASK)

in_nmi判断当前是否在NMI中断上下文。

既然如此,咱们再结合内核抢占调度的情况,看下抢占调度函数

asmlinkage void __sched notrace preempt_schedule(void)
{
struct thread_info *ti = current_thread_info(); /*
* If there is a non-zero preempt_count or interrupts are disabled,
* we do not want to preempt the current task. Just return..
*/
if (likely(ti->preempt_count || irqs_disabled()))
return; do {
add_preempt_count_notrace(PREEMPT_ACTIVE);
__schedule();
sub_preempt_count_notrace(PREEMPT_ACTIVE); /*
* Check again in case we missed a preemption opportunity
* between schedule and now.
*/
barrier();
} while (need_resched());
}

可以看到这里进入函数起始,便对当前线程的preempt_count进行了判断,根据上面的介绍,当内核处理任何一个上下文中时,preempt_count均不可能为0,所以我们也可以根据此发现在软中断、硬件中断、禁止内核抢占、NMI上下文中均不允许调度。当然,我们看到后面后又个irqs_disabled,意味着如果当前禁用了硬件中断,则同样不会发生抢占调度。

补充:

关闭中断的实质是设置EFLAGS寄存器的IF标志位,CLI指令可执行这一操作,当标志位被设置为0时,表示当前关闭中断状态,而STI指令开中断,二者匹配使用。这里的中断指的是可屏蔽的硬件中断。

参考资料:

LInux3.10.1内核源码

LInux中ThreadInfo中的preempt_count字段的更多相关文章

  1. linux运维中的命令梳理(三)

    ----------文本操作命令---------- sed命令:文本编辑工具 sed是一个很好的文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行替换.删除.新增.选取等特 ...

  2. 专家解读Linux操作系统内核中的GCC特性

    专家解读Linux操作系统内核中的GCC特性   Linux内核使用GNU Compiler Collection (GCC)套件的几个特殊功能.这些功能包括提供快捷方式和简化以及向编译器提供优化提示 ...

  3. 详解Linux下iptables中的DNAT与SNAT设置(转)

    详解Linux下iptables中的DNAT与SNAT设置 这篇文章主要介绍了Linux下iptables中的DNAT与SNAT设置,是Linux网络配置中的基础知识,需要的朋友可以参考下   原文连 ...

  4. Linux 2.6 中的文件锁

    简介: 本文的目的是想帮助读者理清 Linux 2.6中文件锁的概念以及 Linux 2.6 都提供了何种数据结构以及关键的系统调用来实现文件锁,从而可以帮助读者更好地使用文件锁来解决多个进程读取同一 ...

  5. Linux设备驱动中的软件架构思想

    目录 更新记录 一.Linux驱动的软件架构 1.1 出发点 1.2 分离思想 1.3 分层思想 二.platform设备驱动 2.1 platform设备 2.2 platform驱动 2.3 pl ...

  6. 基於tiny4412的Linux內核移植--- 中斷和GPIO學習(3)

    作者 彭東林 pengdonglin137@163.com 平臺 tiny4412 ADK Linux-4.4.4 u-boot使用的U-Boot 2010.12,是友善自帶的,爲支持設備樹和uIma ...

  7. 删除数据表中除id外其他字段相同的冗余信息

    删除一个信息表中除id外其他字段都相同的冗余信息,如下 id name addr 1 a b 2 a b 3 b c 删除这个表中的冗余信息 即应该是 id name addr 1 a b 3 b c ...

  8. linux top命令中各cpu占用率含义

    linux top命令中各cpu占用率含义 [尊重原创文章摘自:http://www.iteye.com/topic/1137848]0.3% us 用户空间占用CPU百分比 1.0% sy 内核空间 ...

  9. SQL查询数据库中所有指定类型的字段名称和所在的表名

    --查询数据库中所有指定类型的字段名称和所在的表名 --eg: 下面查的是当前数据库中 所有字段类型为 nvarchar(max) 的字段名和表名 SELECT cols.object_id , co ...

随机推荐

  1. Bootstrap学习笔记(2)--栅格系统深入学习

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. web.config中的connectionString里面应该怎么写?

    2009-09-16 10:19信欣玛利 | 浏览 6068 次  网络 就是具体格式.. 谁能举个例子? asp.net 3.5的. 2009-09-16 10:40   提问者采纳   这是用来连 ...

  3. MapReduce原理<转>

    江湖传说永流传:谷歌技术有"三宝",GFS.MapReduce和大表(BigTable)! 谷歌在03到06年间连续发表了三篇很有影响力的文章,分别是03年SOSP的GFS,04年 ...

  4. Spring整合activiti单元测试

    ** * Spring测试activiti配置是否正常 * <p>Title: SpringActivitiTest</p> * <p>Description: & ...

  5. 用Zend OPCache提高PHP的性能

    Zend OPCache的前身是Zend Optimizer + (Zend O+),在PHP5.5的发行版本中自带了Zend O+,并重新命名为:Zend OPCache.但是默认是没有启用的,可以 ...

  6. 扫描线 - UVALive - 6864 Strange Antennas

    Strange Antennas Problem's Link: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=87213 M ...

  7. 关于为空必填js判断

    为了减少一不必要的if逻辑判断,自已写了一个方法 $(function () { $("#btnAdd").click(function () { var strLinValu = ...

  8. JavaScript语言精粹读书笔记- JavaScript对象

    JavaScript 对象 除了数字.字符串.布尔值.null.undefined(都不可变)这5种简单类型,其他都是对象. JavaScript中的对象是可变的键控集合(keyed collecti ...

  9. 第二百五十四节,Bootstrap项目实战--案例

    Bootstrap项目实战--案例 html <!DOCTYPE html> <html lang="zh-cn"> <head> <me ...

  10. Servlet的线程是不是共享同一个requset对象及servlet多线程

    servlet多线程   一,servlet容器如何同时处理多个请求. Servlet采用多线程来处理多个请求同时访问,Servelet容器维护了一个线程池来服务请求.线程池实际上是等待执行代码的一组 ...