Background

Linux Kernels

entry image

linux kernel

Interrupts

I/O interrupt

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_desc struct

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;
...

Access kernel statistic from the userspace

~$ 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
...

Number of IRQs

$ dmesg | grep NR_IRQS
[    0.000000] NR_IRQS:4352 nr_irqs:488 16

stack frame after non maskable interrupt NMI:

+-------------------------+
| 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               |
+-------------------------+

RCU subsystem

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. 

Pending interrupt or SoftIrq

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

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,
};
...

Ref

linux insides