admin管理员组文章数量:1794759
preempt
kernel通过preempt_count变量来判断是否处于中断(soft/hard/nmi)上下文,是否可以抢占,先看示例
#define in_irq() (hardirq_count())
#define hardirq_count() (preempt_count() & HARDIRQ_MASK)
static __always_inline int preempt_count(void)
{return current_thread_info()->preempt_count;
}static inline struct thread_info *current_thread_info(void) __attribute_const__;struct thread_info {unsigned long flags; /* low level flags */int preempt_count; /* 0 => preemptable, <0 => bug */mm_segment_t addr_limit; /* address limit */struct task_struct *task; /* main task structure */__u32 cpu; /* cpu */__u32 cpu_domain; /* cpu domain */struct cpu_context_save cpu_context; /* cpu context */__u32 syscall; /* syscall number */__u8 used_cp[16]; /* thread used copro */unsigned long tp_value[2]; /* TLS registers */
#ifdef CONFIG_CRUNCHstruct crunch_state crunchstate;
#endifunion fp_state fpstate __attribute__((aligned(8)));union vfp_state vfpstate;
#ifdef CONFIG_ARM_THUMBEEunsigned long thumbee_state; /* ThumbEE Handler Base register */
#endif
};
preempt_count具体定义
linux/preempt.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_NEED_RESCHED: 0x80000000*/
#define PREEMPT_BITS 8
#define SOFTIRQ_BITS 8
#define HARDIRQ_BITS 4
#define NMI_BITS 1#define PREEMPT_SHIFT 0
#define SOFTIRQ_SHIFT (PREEMPT_SHIFT + PREEMPT_BITS)
#define HARDIRQ_SHIFT (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
#define NMI_SHIFT (HARDIRQ_SHIFT + HARDIRQ_BITS)#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)
#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT)
#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
#define NMI_OFFSET (1UL << NMI_SHIFT)#define SOFTIRQ_DISABLE_OFFSET (2 * SOFTIRQ_OFFSET)/* We use the MSB mostly because its available */
#define PREEMPT_NEED_RESCHED 0x80000000/* preempt_count() and related functions, depends on PREEMPT_NEED_RESCHED */
#include <asm/preempt.h>#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))/** Are we doing bottom half or hardware interrupt processing?** in_irq() - We're in (hard) IRQ context* in_softirq() - We have BH disabled, or are processing softirqs* in_interrupt() - We're in NMI,IRQ,SoftIRQ context or have BH disabled* in_serving_softirq() - We're in softirq context* in_nmi() - We're in NMI context* in_task() - We're in task context** Note: due to the BH disabled confusion: in_softirq(),in_interrupt() really* should not be used in new code.*/
#define in_irq() (hardirq_count())
#define in_softirq() (softirq_count())
#define in_interrupt() (irq_count())
#define in_serving_softirq() (softirq_count() & SOFTIRQ_OFFSET)
#define in_nmi() (preempt_count() & NMI_MASK)
#define in_task() (!(preempt_count() & \(NMI_MASK | HARDIRQ_MASK | SOFTIRQ_OFFSET)))
NMI (Non Maskable Interrupt)
硬中断会有如下流程,如PPI和SPI
int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq,bool lookup, struct pt_regs *regs)
{irq_enter();irq = irq_find_mapping(domain, hwirq);generic_handle_irq(irq);irq_exit();}void irq_enter(void){preempt_count_add(HARDIRQ_OFFSET);
}void irq_exit(void)
{preempt_count_sub(HARDIRQ_OFFSET);
}
软中断处理函数
asmlinkage __visible void __softirq_entry __do_softirq(void)
{__local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET);
restart:........................................__local_bh_enable(SOFTIRQ_OFFSET);
}static __always_inline void __local_bh_disable_ip(unsigned long ip, unsigned int cnt)
{preempt_count_add(cnt);
}
static void __local_bh_enable(unsigned int cnt)
{preempt_count_sub(cnt);
}
#define preempt_disable() \
do { \preempt_count_inc(); \barrier(); \
} while (0)
#define preempt_enable() \
do { \barrier(); \if (unlikely(preempt_count_dec_and_test())) \__preempt_schedule(); \
} while (0)
本文标签: preempt
版权声明:本文标题:preempt 内容由林淑君副主任自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.xiehuijuan.com/baike/1693175702a243298.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论