前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >preempt_count

preempt_count

作者头像
DragonKingZhu
发布2020-03-24 11:15:52
8690
发布2020-03-24 11:15:52
举报

定义

代码语言:javascript
复制
/*
 * 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的各个字段的定义:

代码语言:javascript
复制
<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系统为了方便得出各个字段的值,提供了一系列宏定义如下:

代码语言:javascript
复制
#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。

各种上下文

代码语言:javascript
复制
/*
 * 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这一位来判断。

代码语言:javascript
复制
#define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != 0)

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 定义
  • 字段含义
  • 相关宏定义
  • 各种上下文
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档