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
相关文章推荐
- centos6.5环境通达OA数据库mysql5.0.67升级至mysql5.5.48方案
- centos6.5环境通达OA数据库mysql5.0.67升级至mysql5.5.48方案
- vmare 下的linux和windows 通过ftp互换文件
- 20145219 《Java程序设计》实验一 Java开发环境的熟悉(Linux + Eclipse)实验报告
- ITerm2下使用ssh访问Linux
- Linux 中常见问题总结
- 实现windows操作系统和VB下Linux虚拟操作系统相互传取文件方式总结
- JPEG 原理详细实例分析及其在嵌入式 Linux 中的应用
- linux下ImageMagick convert命令
- Linux下手动安装 firefox 6 并且添加快捷方式图标
- cmake在linux,windows,mac下的安装与使用
- linux基础知识题解答(九)
- ssh免密码登录
- linux下统计当前文件夹中文件的数目以及如何查看文件夹的大小
- linux下查找某一类型的文件方法
- linux中进程间如何通信的?
- Linux查看CPU和内存使用情况
- linux安装jdk1.7
- 学习笔记之linux内存分配读书笔记
- Linux源码编译安装MySQL5.7