您的位置:首页 > 运维架构 > Linux

linux interrupt, deferrable function

2016-04-08 19:15 821 查看

x86

Take x86 architecture for example:

kernel/include/linux/thread_info.h

kernel/arch/x86/include/asm/thread_info.h

struct thread_info 在CPU体系架构相关的thread_info.h文件中定义,不在公共的linux/thread_info.h中定义,以x86为例:

struct thread_info
{
struct task_struct  *task;      /* main task structure */
struct exec_domain  *exec_domain;   /* execution domain */
__u32           flags;      /* low level flags */
__u32           status;     /* thread synchronous flags */
__u32           cpu;        /* current CPU */
int         preempt_count;  /* 0 => preemptable,
<0 => BUG */
mm_segment_t        addr_limit;
struct restart_block    restart_block;
void __user     *sysenter_return;
#ifdef CONFIG_X86_32
unsigned long           previous_esp;   /* ESP of the previous stack in
case of nested (IRQ) stacks
*/
__u8            supervisor_stack[0];
#endif
unsigned int        sig_on_uaccess_error:1;
unsigned int        uaccess_err:1;  /* uaccess failed */
};


int         preempt_count;  /* 0 => preemptable,
<0 => BUG */
linux/hardirq.h 中:
#define in_interrupt()      (irq_count())
===>
#define irq_count() (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK | NMI_MASK))
===>

both hardirq counter and softirq counter are put into the preemption counter:
- bits 0-7 are the preemption count (max preemption depth: 256)
- bits 8-15 are the softirq count (max # of softirqs: 256)
- 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

#define in_irq()        (hardirq_count())
#define in_softirq()        (softirq_count())
#define in_interrupt()      (irq_count())
#define in_serving_softirq()    (softirq_count() & SOFTIRQ_OFFSET)

这些宏用来获取 irq,softirq,interrupt的数量。

在 kernel/arch/x86/kernel/irq_32.c 中:
asmlinkage void do_softirq(void)
{
...
if (in_interrupt())
return;
...
}
如果in_interrupt()返回值不为0,则直接返回;


kernel/arch/x86/include/asm/thread_info.h 中定义:

/* how to get the current stack pointer from C */
register unsigned long current_stack_pointer asm("esp") __used;

(1) register关键字
C语言中的一个关键字;

(2) __used 作用?
此处的__used是一个宏,代码中有多处定义,例如一处是:
#if GCC_VERSION >= 30300
# define __used         __attribute__((__used__))
#else
# define __used         __attribute__((__unused__))
#endif
所以要根据包含的头文件来判断;

(3) asm("esp") 是什么语法?
此处的 esp 是寄存器的名字,不是汇编指令;
esp points to the top of the stack


arm

Take arm architecture for example:

kernel/include/linux/thread_info.h

kernel/arch/arm/include/asm/thread_info.h

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 */
struct exec_domain  *exec_domain;   /* execution domain */
__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_CRUNCH
struct crunch_state crunchstate;
#endif
union fp_state      fpstate __attribute__((aligned(8)));
union vfp_state     vfpstate;
#ifdef CONFIG_ARM_THUMBEE
unsigned long       thumbee_state;  /* ThumbEE Handler Base register */
#endif
struct restart_block    restart_block;
};


/*
* how to get the thread information struct from C
*/
static inline struct thread_info *current_thread_info(void) __attribute_const__;

static inline struct thread_info *current_thread_info(void)
{
register unsigned long sp asm ("sp");

return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
}

在 kernel/arch/arm/include/asm/thread_info.h 文件中:
#define THREAD_SIZE     8192

THREAD_SIZE 8192,二进制
10 0000 0000 0000
——————————————————————————————————————
8192 -1 = 8191,二进制
1 1111 1111 1111
——————————————————————————————————————
~(THREAD_SIZE - 1),如果是32位,则:
1111 1111 1111 1111 1110 0000 0000 0000
——————————————————————————————————————
sp & ~(THREAD_SIZE - 1) 则是sp中的值(这个地址),低13位全部为0,

有个问题,这个堆栈是从低地址到高地址吗?如果不是的话,这个函数的逻辑不成立?




local interrupt disabling

local_irq_disable() : make use of the cli assembly language instruction, disable interrupts on the local CPU

local_irq_enable() : make use of the sti assembly language instruction, enable them

local_irq_save()
local_irq_restore()

eflags

call sequence:
local_irq_disable()
local_irq_save()
...
local_irq_restore()
local_irq_enable()


disabling and enabling deferrable functions

kernel sometimes needs to disable deferrable functions without disabling interrupts
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: