1. /kernel/irq.c softirq_init 2.6.32.25
1.1 for_each_possible_cpu for ( ( ( cpu ) ) = - 1 ; ( ( cpu ) ) = cpumask_next ( ( ( cpu ) ) , ( cpu_possible_mask ) ) , ( ( cpu ) ) < nr_cpu_ids ; )
1.2 per_cpu(tasklet_vec, cpu);
//取per_cpu_tasklet_vec[cpu],即cpu的tasklet_vec结构。per_cpu(tasklet_vec, cpu);
( * ( { unsigned long __ptr ; __ptr = ( unsigned long ) ( ( & per_cpu__tasklet_vec ) ) ; ( typeof ( ( & per_cpu__tasklet_vec ) ) ) ( __ptr + ( ( ( __per_cpu_offset [ cpu ] ) ) ) ) ; } ) ) ;
1.3 tasklet_vec / tasklet_hi_vec

static DEFINE_PER_CPU(struct tasklet_head, tasklet_vec);
static DEFINE_PER_CPU(struct tasklet_head, tasklet_vec);
static __attribute__ ( ( section ( ".data.percpu" ) ) ) __typeof__ ( struct tasklet_head ) per_cpu__tasklet_vec ;

static DEFINE_PER_CPU(struct tasklet_head, tasklet_hi_vec);static DEFINE_PER_CPU(struct tasklet_head, tasklet_hi_vec);
static __attribute__ ( ( section ( ".data.percpu" ) ) ) __typeof__ ( struct tasklet_head ) per_cpu__tasklet_hi_vec ;
struct tasklet_headstruct tasklet_head{
struct tasklet_struct *head;
struct tasklet_struct **tail;
};
struct tasklet_structstruct tasklet_struct{
struct tasklet_struct *next;
unsigned long state;
atomic_t count;
void (*func)(unsigned long);
unsigned long data;
};
1.4 softirq_work_list
DECLARE_PER_CPU(struct list_head [NR_SOFTIRQS], softirq_work_list);DECLARE_PER_CPU(struct list_head [NR_SOFTIRQS], softirq_work_list);
extern __attribute__ ( ( section ( ".data.percpu" ) ) ) __typeof__ ( struct list_head [ NR_SOFTIRQS ] ) per_cpu__softirq_work_list ;
DEFINE_PER_CPU(struct list_head [NR_SOFTIRQS], softirq_work_list);DEFINE_PER_CPU(struct list_head [NR_SOFTIRQS], softirq_work_list);
__attribute__ ( ( section ( ".data.percpu" ) ) ) __typeof__ ( struct list_head [ NR_SOFTIRQS ] ) per_cpu__softirq_work_list ;
1.5 x86_init extern struct x86_init_ops x86_init;
struct x86_init_ops {
struct x86_init_resources resources;
struct x86_init_mpparse mpparse;
struct x86_init_irqs irqs;
struct x86_init_oem oem;
struct x86_init_paging paging;
struct x86_init_timers timers;
};
struct x86_init_resources {
void (*probe_roms)(void);
void (*reserve_resources)(void);
char *(*memory_setup)(void);
};
struct x86_init_mpparse {
void (*mpc_record)(unsigned int mode);
void (*setup_ioapic_ids)(void);
int (*mpc_apic_id)(struct mpc_cpu *m);
void (*smp_read_mpc_oem)(struct mpc_table *mpc);
void (*mpc_oem_pci_bus)(struct mpc_bus *m);
void (*mpc_oem_bus_info)(struct mpc_bus *m, char *name);
void (*find_smp_config)(unsigned int reserve);
void (*get_smp_config)(unsigned int early);
};
struct x86_init_irqs {
void (*pre_vector_init)(void);
void (*intr_init)(void);
void (*trap_init)(void);
};
struct x86_init_oem {
void (*arch_setup)(void);
void (*banner)(void);
};
struct x86_init_paging {
void (*pagetable_setup_start)(pgd_t *base);
void (*pagetable_setup_done)(pgd_t *base);
};
struct x86_init_timers {
void (*setup_percpu_clockev)(void);
void (*tsc_pre_init)(void);
void (*timer_init)(void);
};
1.6 test_and_set_bit
BTS—Bit Test and Set
Description:
Selects the bit in a bit string (specified with the first operand, called the bit base) at the bit-position designated by the bit offset operand (second operand), stores the value of the bit in the CF flag, and sets the selected bit in the bit string to 1. The bit base operand can be a register or a memory location; the bit offset operand can be a register or an immediate value:
• If the bit base operand specifies a register, the instruction takes the modulo 16, 32, or 64 of the bit offset operand (modulo size depends on the mode and register size; 64-bit operands are available only in 64-bit mode). This allows any bit position to be selected.
• If the bit base operand specifies a memory location, the operand represents the address of the byte in memory that contains the bit base (bit 0 of the specified byte) of the bit string. The range of the bit position that can be referenced by the offset operand depends on the operand size.
See also: Bit(BitBase, BitOffset) on page 3-14.
Some assemblers support immediate bit offsets larger than 31 by using the imme-diate bit offset field in combination with the displacement field of the memory operand. See “BT—Bit Test” in this chapter for more information on this addressing mechanism.
This instruction can be used with a LOCK prefix to allow the instruction to be executed atomically.
In 64-bit mode, the instruction’s default operation size is 32 bits. Using a REX prefix in the form of REX.R permits access to additional registers (R8-R15). Using a REX prefix in the form of REX.W promotes operation to 64 bits. See the summary chart at the beginning of this section for encoding data and limits.
Operation
CF ← Bit(BitBase, BitOffset);
Bit(BitBase, BitOffset) ← 1;
Flags Affected
The CF flag contains the value of the selected bit before it is set. The ZF flag is unaf-
fected. The OF, SF, AF, and PF flags are undefined.
SBB—Integer Subtraction with Borrow;
Description:
Adds the source operand (second operand) and the carry (CF) flag, and subtracts the result from the destination operand (first operand). The result of the subtraction is stored in the destination operand. The destination operand can be a register or a memory location; the source operand can be an immediate, a register, or a memory location. (However, two memory operands cannot be used in one instruction.) The state of the CF flag represents a borrow from a previous subtraction.
When an immediate value is used as an operand, it is sign-extended to the length of the destination operand format.
The SBB instruction does not distinguish between signed or unsigned operands. Instead, the processor evaluates the result for both data types and sets the OF and CF flags to indicate a borrow in the signed or unsigned result, respectively. The SF flag indicates the sign of the signed result.
The SBB instruction is usually executed as part of a multibyte or multiword subtrac-tion in which a SUB instruction is followed by a SBB instruction.
This instruction can be used with a LOCK prefix to allow the instruction to be executed atomically.
In 64-bit mode, the instruction’s default operation size is 32 bits. Using a REX prefix in the form of REX.R permits access to additional registers (R8-R15). Using a REX prefix in the form of REX.W promotes operation to 64 bits. See the summary chart at the beginning of this section for encoding data and limits.
Operation
DEST ← (DEST – (SRC + CF));
Flags Affected
The OF, SF, ZF, AF, PF, and CF flags are set according to the result.// \linux-2.6.32.25\arch\x86\include\asm\ bitops.h
static inline int test_and_set_bit(int nr, volatile unsigned long *addr){
int oldbit;
asm volatile(LOCK_PREFIX "bts %2,%1\n\t"
"sbb %0,%0" : "=r" (oldbit), ADDR : "Ir" (nr) : "memory");
return oldbit;
}
#define ADDR BITOP_ADDR(addr)
#define BITOP_ADDR(x) "=m" (*(volatile long *) (x))
#define LOCK_PREFIX \
".section .smp_locks,\"a\"\n" \
_ASM_ALIGN "\n" \
_ASM_PTR "661f\n" /* address */ \
".previous\n" \
"661:\n\tlock; "
#define _ASM_ALIGN __ASM_SEL(.balign 4, .balign 8)
#define _ASM_PTR __ASM_SEL(.long, .quad)
#define __ASM_SEL(a,b) __ASM_FORM(a)
#ifdef __ASSEMBLY__
#define __ASM_FORM(x) x
#define __ASM_EX_SEC .section __ex_table, "a"
#else
# define __ASM_FORM(x) " " #x " "
# define __ASM_EX_SEC " .section __ex_table,\"a\"\n"
#endif
LOCK_PRIFIX根据宏定义展开过后为:".section .smp_locks,\"a\"\n .balign 4 \n .long 661f\n.previous\n661:\n\tlock; " ;
//\linux-2.6.32.25\include\asm-generic\bitops\ atomic.h
static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
unsigned long old;
unsigned long flags;
_atomic_spin_lock_irqsave(p, flags);
old = *p;
*p = old | mask;
_atomic_spin_unlock_irqrestore(p, flags);
return (old & mask) != 0;
}
有两个test_and_set_bit定义,一直搞不清楚到底是用的哪一个,什么时候用哪一个?分析了第一个,第二个还没来得及分析。
2. raise_softirq_irqoff softirq.c 2.6.38.2
2.1 重要宏定义和数据结构 1. /*Softirq.c*/
2. void raise_softirq(unsigned int nr)
3. {
4. unsigned long flags;
5.
6. local_irq_save(flags);
7.raise_softirq_irqoff(nr);
8. local_irq_restore(flags);
9. }
10.
11. /*Softirq.c*/
12. inline void raise_softirq_irqoff(unsigned int nr)
13. {
14.__raise_softirq_irqoff(nr);
15.
16. /*
17. * If we're in an interrupt or softirq, we're done
18. * (this also catches softirq-disabled code). We will
19. * actually run the softirq once we return from
20. * the irq or softirq.
21. *
22. * Otherwise we wake up ksoftirqd to make sure we
23. * schedule the softirq soon.
24. */
25. if (!in_interrupt())
26. wakeup_softirqd();
27. }
28.
29. /*include/linux/Interrupt.h*/
30. static inline void __raise_softirq_irqoff(unsigned int nr)
31. {
32. trace_softirq_raise(nr);
33.or_softirq_pending(1UL << nr);
34. }
35.
36. /*include/linux/Interrupt.h*/
37. #ifndef __ARCH_SET_SOFTIRQ_PENDING
38. #define set_softirq_pending(x) (local_softirq_pending() = (x))
39. #define or_softirq_pending(x) (local_softirq_pending() |= (x))
40. #endif
41.
42.
43. /*include/linux/Interrupt.h*/
44. #ifndef __ARCH_IRQ_STAT
45. extern irq_cpustat_t irq_stat[]; /* defined in asm/hardirq.h */
46. #define __IRQ_STAT(cpu, member) (irq_stat[cpu].member)
47. #endif
48.
49. /* arch independent irq_stat fields */
50.#definelocal_softirq_pending() \
51.__IRQ_STAT(smp_processor_id(), __softirq_pending)
52. /********************************************************/
53. /*arch/x86/include/asm/Hardirq.h*/
54. typedef struct {
55. unsigned int __softirq_pending;
56. unsigned int __nmi_count; /* arch dependent */
57. unsigned int irq0_irqs;
58. #ifdef CONFIG_X86_LOCAL_APIC
59. unsigned int apic_timer_irqs; /* arch dependent */
60. unsigned int irq_spurious_count;
61. #endif
62. unsigned int x86_platform_ipis; /* arch dependent */
63. unsigned int apic_perf_irqs;
64. unsigned int apic_irq_work_irqs;
65. #ifdef CONFIG_SMP
66. unsigned int irq_resched_count;
67. unsigned int irq_call_count;
68. unsigned int irq_tlb_count;
69. #endif
70. #ifdef CONFIG_X86_THERMAL_VECTOR
71. unsigned int irq_thermal_count;
72. #endif
73. #ifdef CONFIG_X86_MCE_THRESHOLD
74. unsigned int irq_threshold_count;
75. #endif
76.} ____cacheline_aligned irq_cpustat_t;
77.
78.DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
79.
80. /*include/linux/percpu_defs.h*/
81. #define DECLARE_PER_CPU_SHARED_ALIGNED(type, name) \
82. DECLARE_PER_CPU_SECTION(type, name, PER_CPU_SHARED_ALIGNED_SECTION) \
83. ____cacheline_aligned_in_smp
84. #define DECLARE_PER_CPU_SECTION(type, name, sec) \
85. extern __PCPU_ATTRS(sec) __typeof__(type) name
86.
87. #define __PCPU_DUMMY_ATTRS \
88. __attribute__((section(".discard"), unused))
89.
90. #define __PCPU_ATTRS(sec) \
91. __percpu __attribute__((section(PER_CPU_BASE_SECTION sec))) \
92. PER_CPU_ATTRIBUTES
93.
94.
95. /*include/asm-generic/Percpu.h*/
96. #define PER_CPU_SHARED_ALIGNED_SECTION "..shared_aligned"
97.
98. #ifndef PER_CPU_ATTRIBUTES
99. #define PER_CPU_ATTRIBUTES
100. #endif
101. /*include/linux/Cache.h*/
102. #define ____cacheline_aligned_in_smp ____cacheline_aligned
103.
104.
105. /*include/linux/compiler.h*/
106. # define __percpu
2.2 or_softirq_pending ( 1UL << nr ) ; ( irq_stat [ smp_processor_id ( ) ] . __softirq_pending ) |= ( 1UL << nr ) ) ;
2.3 local_softirq_pending(); ( irq_stat [ smp_processor_id ( ) ] . __softirq_pending ) ;
2.4 DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); extern __attribute__ ( ( section ( PER_CPU_BASE_SECTION "..shared_aligned" ) ) ) __typeof__ ( irq_cpustat_t ) irq_stat ____cacheline_aligned ;
2.5 irq_cpustat_t /*arch/x86/include/asm/Hardirq.h*/
typedef struct {
unsigned int __softirq_pending;
unsigned int __nmi_count; /* arch dependent */
unsigned int irq0_irqs;
#ifdef CONFIG_X86_LOCAL_APIC
unsigned int apic_timer_irqs; /* arch dependent */
unsigned int irq_spurious_count;
#endif
unsigned int x86_platform_ipis; /* arch dependent */
unsigned int apic_perf_irqs;
unsigned int apic_irq_work_irqs;
#ifdef CONFIG_SMP
unsigned int irq_resched_count;
unsigned int irq_call_count;
unsigned int irq_tlb_count;
#endif
#ifdef CONFIG_X86_THERMAL_VECTOR
unsigned int irq_thermal_count;
#endif
#ifdef CONFIG_X86_MCE_THRESHOLD
unsigned int irq_threshold_count;
#endif
} ____cacheline_aligned irq_cpustat_t;
2.6 流程总结



本文深入探讨了Micropython中中断处理和函数指针的使用,通过分析kernel/irq.c文件,展示了初始化过程,如per_cpu变量的获取,tasklet_vec和tasklet_hi_vec结构,以及softirq_work_list。此外,还讨论了x86_init结构体及其各个子结构体的作用。最后,简要介绍了raise_softirq_irqoff函数的工作原理,包括软中断的触发和状态管理。
243

被折叠的 条评论
为什么被折叠?



