when an I/O interrupt occurred:
• Save the value of an IRQ and the register's contents on the kernel stack;
• Send an acknowledgment to the hardware controller which is servicing the IRQ line;
• Execute the interrupt service routine (next we will call it ISR) which is associated with the device;
• Restore registers and return from an interrupt;
irq_common_data - per irq and chip data passed down to chip functions
status_use_accessors – enum and macros from include/linux/irq.h
kstat_irqs - irq stats per-cpu
handle_irq - highlevel irq-events handler
action - identifies the interrupt service routines to be invoked when the IRQ occurs
irq_count - counter of interrupt occurrences on the IRQ line
depth - 0 if the IRQ line is enabled and a positive value if it has been disabled at least once
last_unhandled - aging timer for unhandled count
irqs_unhandled - count of the unhandled interrupts
lock - a spin lock used to serialize the accesses to the IRQ descriptor
pending_mask - pending rebalanced interrupts
owner - an owner of interrupt descriptor. module which provides the interrupts;
...
~$ cat /proc/stat
cpu 207907 68 53904 5427850 14394 0 394 0 0 0
cpu0 25881 11 6684 679131 1351 0 18 0 0 0
cpu1 24791 16 5894 679994 2285 0 24 0 0 0
cpu2 26321 4 7154 678924 664 0 71 0 0 0
cpu3 26648 8 6931 678891 414 0 244 0 0 0
...
$ dmesg | grep NR_IRQS
[ 0.000000] NR_IRQS:4352 nr_irqs:488 16
+-------------------------+
| original SS |
| original Return RSP |
| original RFLAGS |
| original CS |
| original RIP |
+-------------------------+
| temp storage for rdx |
+-------------------------+
| NMI executing variable | maybe = 1
+-------------------------+
| copied SS |
| copied Return RSP |
| copied RFLAGS |
| copied CS |
| copied RIP |
+-------------------------+
| Saved SS |
| Saved Return RSP |
| Saved RFLAGS |
| Saved CS |
| Saved RIP |
+-------------------------+
Number of the rcu nodes determined by the NUM_RCU_NODES
*** which depends on number of available CPUs:
#define NUM_RCU_NODES (RCU_SUM - NR_CPUS)
#define RCU_SUM (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2 + NUM_RCU_LVL_3 + NUM_RCU_LVL_4)
where levels values depend on the CONFIG_RCU_FANOUT_LEAF configuration option.
For example for the simplest case,
*** one rcu_node will cover two CPU on machine with the eight CPUs:
+-----------------------------------------------------------------+
| rcu_state |
| +----------------------+ |
| | root | |
| | rcu_node | |
| +----------------------+ |
| | | |
| +----v-----+ +--v-------+ |
| | | | | |
| | rcu_node | | rcu_node | |
| | | | | |
| +------------------+ +----------------+ |
| | | | | |
| | | | | |
| +----v-----+ +-------v--+ +-v--------+ +-v--------+ |
| | | | | | | | | |
| | rcu_node | | rcu_node | | rcu_node | | rcu_node | |
| | | | | | | | | |
| +----------+ +----------+ +----------+ +----------+ |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
+---------|-----------------|-------------|---------------|-------+
| | | |
+---------v-----------------v-------------v---------------v--------+
| | | | |
| CPU1 | CPU3 | CPU5 | CPU7 |
| | | | |
| CPU2 | CPU4 | CPU6 | CPU8 |
| | | | |
+------------------------------------------------------------------+
rcu_init_geometry function
*** we just need to calculate the total number of rcu_node structures.
delayed for later execution
when the system is less loaded.
struct softirq_action
{
void (*action)(struct softirq_action *); //handler of interrupt
};
$ cat /proc/softirqs
CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7
HI: 2 0 0 1 0 2 0 0
TIMER: 137779 108110 139573 107647 107408 114972 99653 98665
NET_TX: 1127 0 4 0 1 1 0 0
NET_RX: 334 221 132939 3076 451 361 292 303
BLOCK: 5253 5596 8 779 2016 37442 28 2855
BLOCK_IOPOLL: 0 0 0 0 0 0 0 0
TASKLET: 66 0 2916 113 0 24 26708 0
SCHED: 102350 75950 91705 75356 75323 82627 69279 69914
HRTIMER: 510 302 368 260 219 255 248 246
RCU: 81290 68062 82979 69015 68390 69385 63304 63473
vector_irq per-cpu array
which is store vector numbers of the interrupts
which is related to the external hardware interrupts
...
DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
[0 ... NR_VECTORS - 1] = -1,
};
...
linux insides