linux interrupt, deferrable function

来源:互联网 发布:网络维修基础知识 编辑:程序博客网 时间:2024/05/18 02:42

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     8192THREAD_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 CPUlocal_irq_enable() : make use of the sti assembly language instruction, enable themlocal_irq_save()local_irq_restore()eflagscall 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
0 0