1 Overview of softinterrupt

Soft interrupt is a way to realize the lower part of interrupt , And 2.5 The mechanism of the second half of the previous version is different . Soft interrupts can run in different environments at the same time CPU On .

1.1 Soft interrupt representation

Structure is used in the kernel softirq_action Represents a soft interrupt . Softinterrupts are a set of statically defined interfaces , Yes 32 individual . But the kernel (2.6.34) Only... Has been achieved in 10 individual . The number of available softinterrupts NR_SOFTIRQ Express ,NR_SOFTIRQ=10, The type of soft interrupt is represented by an enumeration body . What needs to be noted here is ,32 The bit mask of each soft interrupt is unsigned int type .

static struct softirq_action softirq_vec[NR_SOFTIRQS] ;
enum
{
HI_SOFTIRQ=0,
TIMER_SOFTIRQ,
NET_TX_SOFTIRQ,
NET_RX_SOFTIRQ,
BLOCK_SOFTIRQ,
BLOCK_IOPOLL_SOFTIRQ,
TASKLET_SOFTIRQ,
SCHED_SOFTIRQ,
HRTIMER_SOFTIRQ,
RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */ NR_SOFTIRQS
};
struct softirq_action
{
void (*action)(struct softirq_action *);
};

2 Soft interrupt related data structure

2.1 thread_info Of preempt_count Field

preempt_count It's a 32 Bit int type , Will be divided into 5 A field



macro in_interrupt Detect soft interrupt counter Hard interrupt counter and NMI Mask , As long as any of the three fields is not 0, Indicates that the process is in the interrupt context .

#define in_irq() (hardirq_count())
#define in_softirq() (softirq_count())
#define in_interrupt() (irq_count())

2.2 pending Bitmask

Every CPU There's a irq_stat structure ,irq_stat Medium __softirq_pending It's a 32 Bit mask , by 1 Indicates that the soft interrupt has been activated , Waiting to be processed . by 0 Indicates that soft interrupt is disabled . stay do_irq Is used in .

The kernel using local_softirq_pending Get the present CPU Bit mask on

#define local_softirq_pending() percpu_read(irq_stat.__softirq_pending)
#define set_softirq_pending(x) percpu_write(irq_stat.__softirq_pending, (x))
#define or_softirq_pending(x) percpu_or(irq_stat.__softirq_pending, (x)) irq_cpustat_t irq_stat[NR_CPUS]
typedef struct {
...
unsigned int __softirq_pending;
...
}irq_cpustat_t;

2.3 Soft interrupt stack

The size of the process's kernel stack depends on the compile time options , It can be 4K perhaps 8K. If it is 8K Stack , interrupt , Exception and soft interrupt (softirq) Share this stack . If you choose 4K Stack , Then the kernel stack Hard interrupt stack Each soft interrupt stack uses one 4K Space . About soft interrupt stack , Later, it will be explained in detail when handling soft interrupt .

#ifdef CONFIG_4KSTACKS
static DEFINE_PER_CPU_PAGE_ALIGNED(union irq_ctx, softirq_stack);
union irq_ctx {
struct thread_info tinfo;
u32 stack[THREAD_SIZE/sizeof(u32)];
} __attribute__((aligned(PAGE_SIZE)));

3 Initialization of soft interrupt

The kernel using open_softirq Initialize a soft interrupt ,nr Is a constant representing the type of soft interrupt ,action Point to a soft interrupt handler

void open_softirq(int nr, void (*action)(struct softirq_action *))
{
softirq_vec[nr].action = action;
}

4 Soft interrupt trigger (raise softirq)

Trigger is to mask bits pending The corresponding bit of Set up 1 The process of . The kernel using raise_softirq Finish triggering soft interrupt ,nr Is the type of soft interrupt to trigger . It's worth noting that , Interrupt trigger In the case of a shutdown hard interrupt .

In the process of triggering soft interrupt , If the process is not in the interrupt context , Indicates that the current process is in the process context , So let's call wakeup_softirqd Dispatch ksoftirqd that will do .

conversely , If you are currently in interrupt context or soft interrupt is disabled , Then you don't have to schedule kernel threads , After interrupt processing irq_exit in , Would call invoke_softirq() Handle soft interrupts .

The actual job is to give or_softirq_pending(1UL << (nr)); Accomplished , This function specifies and... By bit operation pending Add up .

void raise_softirq(unsigned int nr)
{
unsigned long flags;
local_irq_save(flags);
raise_softirq_irqoff(nr);
local_irq_restore(flags);
} inline void raise_softirq_irqoff(unsigned int nr)
{
__raise_softirq_irqoff(nr); /*
* If we're in an interrupt or softirq, we're done
* (this also catches softirq-disabled code). We will
* actually run the softirq once we return from
* the irq or softirq.
*
* Otherwise we wake up ksoftirqd to make sure we
* schedule the softirq soon.
* If not in interrupt context
*/
if (!in_interrupt())
wakeup_softirqd();
} #define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); }

5. Soft interrupt processing

5.1 When to deal with soft interrupt

1 stay do_irq At the end of (irq_exit)

If the current process is not in the interrupt context and is local CPU There are also soft interrupts that are not handled on , So call invoke_softirq() Handle soft interrupts .

#ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED
# define invoke_softirq() __do_softirq()
#else
# define invoke_softirq() do_softirq()
#endif
void irq_exit(void)
{
account_system_vtime(current);
trace_hardirq_exit();
sub_preempt_count(IRQ_EXIT_OFFSET);
if (!in_interrupt() && local_softirq_pending())
invoke_softirq(); rcu_irq_exit();
#ifdef CONFIG_NO_HZ
/* Make sure that timer wheel updates are propagated */
if (idle_cpu(smp_processor_id()) && !in_interrupt() && !need_resched())
tick_nohz_stop_sched_tick(0);
#endif
preempt_enable_no_resched();
} #ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED
# define invoke_softirq() __do_softirq()
#else
# define invoke_softirq() do_softirq()
#endif

Program 5-1 irq_exit

2 When soft interrupts are repeatedly triggered over 10 When the time , The kernel calls wakeup_softirqd() Wake up the kernel thread ksoftirqd To handle soft interrupts .

5.2 Soft interrupt processing

1 do_softirq

According to the kernel stack size , There are two kinds of do_softirq, One is universal do_irq, The other is architecture related do_irq(arch/x86/kernel/irq_32.c).

General purpose do_irq workflow

1 Judge whether it is in the context of hard interrupt or soft interrupt is disabled , If so, go straight back to

2 preservation Eflags Then turn off the local hardware interrupt

3 Access to the local CPU Bit mask for pending If the soft interrupt to be processed is called __do_irq

4 from __do_irq Back to recovery Eflags

asmlinkage void do_softirq(void)
{
// The local variable used to hold the bitmask
__u32 pending;
// preservation Eflags Local variables of registers
unsigned long flags;
// If do_softirq Called in interrupt context or Soft interrupt is forbidden So don't handle soft interrupts
// Go straight back to
if (in_interrupt())
return;
// take Eflags Save to flags in Then turn off the hardware interrupt
local_irq_save(flags);
// Access to the local CPU Bit mask on
pending = local_softirq_pending(); if (pending)
__do_softirq();
// take flags
local_irq_restore(flags);
}

x86_32 Use under architecture 4K Soft interrupt stack do_softirq Processing flow

1 Similar to general do_softirq, If it's in the context of an interrupt or if soft interrupts are disabled, return immediately . Then turn off the external interrupt

2 If the local CPU If there is a soft interrupt to be processed on the stack, the soft interrupt stack will be processed , The key is to make isp Point to the bottom of the soft interrupt stack . Then call... On the soft interrupt stack call_on_stack.call_on_stack It's an inline compilation , Its main purpose is to switch from kernel stack to softinterrupt stack . First the esp Save to ebx in , Use call The command jumps to __do_softirq Subroutines , Subroutines are restored when they return esp.

asmlinkage void do_softirq(void)
{
unsigned long flags;
struct thread_info *curctx;
union irq_ctx *irqctx;
u32 *isp; if (in_interrupt())
return; local_irq_save(flags); if (local_softirq_pending()) {
//curctx Pointing to the current process thread_info structure
curctx = current_thread_info();
//irqctx Contains a soft interrupt heap and thread_info structure
irqctx = __get_cpu_var(softirq_ctx);
// Trigger hard interrupt and soft interrupt are the same process, so threadinfo Of task The pointer is uniform
irqctx->tinfo.task = curctx->task;
// Switch from kernel stack to soft interrupt stack You need to save the stack pointer register contents of the kernel stack
irqctx->tinfo.previous_esp = current_stack_pointer; /* build the stack frame on the softirq stack */
//isp Point to the bottom of soft interrupt stack
isp = (u32 *) ((char *)irqctx + sizeof(*irqctx));
// Call... On the soft interrupt stack __do_softirq
call_on_stack(__do_softirq, isp);
}
local_irq_restore(flags);
} static void call_on_stack(void *func, void *stack)
{
//call *%%edi Indirect absolute near call The offset address is stored in edi In the register
// Instruction execution First the eip Push And then edi-->eip
// Exchange first ebx and esp
// And then call __do_softirq
// And then ebx-->esp recovery xchgl Previous esp
// The output constraint will ebx --> stack
asm volatile("xchgl %%ebx,%%esp \n"
"call *%%edi \n"
"movl %%ebx,%%esp \n"
: "=b" (stack)
: "0" (stack),
"D"(func)
: "memory", "cc", "edx", "ecx", "eax");
}

2 __do_softirq

Soft interrupt is actually handled by __do_softirq complete , The whole idea is to traverse pending, If a bit is not empty, it means local CPU Soft interrupts to be processed on , Call soft interrupt processing function .

Before you start processing soft interrupts , The kernel calls __local_bh_disable( By way of preempt_count Soft interrupt counter plus 1) Close the bottom half . As mentioned before , There is more than one time to deal with soft interrupts , The kernel should be local CPU The processing of soft interrupt is serial .

In addition, at the end of the loop that handles soft interrupts , The kernel also needs to detect whether there are repeated soft interrupts . First call local_softirq_pending() Get bitmask pending, And then according to pending Continue processing soft interrupts , But this kind of repetition can't be more than 10 Time (MAX_SOFTIRQ_RESTART), Once you surpass 10 Time , The kernel will wake up ksoftirqd

#define MAX_SOFTIRQ_RESTART 10
asmlinkage void __do_softirq(void)
{
// softirq_action Represents a soft interrupt
struct softirq_action *h;
// local variable pending Save the pending soft interrupt bitmap
__u32 pending;
// The number of soft interrupt restarts
int max_restart = MAX_SOFTIRQ_RESTART;
int cpu;
// Access to the local CPU All pending soft interrupts on the
pending = local_softirq_pending();
account_system_vtime(current); // Close the bottom half of the interrupt
__local_bh_disable((unsigned long)__builtin_return_address(0));
lockdep_softirq_enter(); cpu = smp_processor_id();
restart:
/* Reset the pending bitmask before enabling irqs */
//pending All the status of soft interrupt has been saved So will pending bitmask clear
set_softirq_pending(0);
// Open the interrupt
local_irq_enable();
//h Point to the first kind of soft interrupt
h = softirq_vec;
do {
// Handle the first kind of soft interrupt first
if (pending & 1) {
int prev_count = preempt_count();
kstat_incr_softirqs_this_cpu(h - softirq_vec); trace_softirq_entry(h, softirq_vec);
// Call soft interrupt handler
h->action(h);
trace_softirq_exit(h, softirq_vec);
if (unlikely(prev_count != preempt_count())) {
printk(KERN_ERR "huh, entered softirq %td %s %p"
"with preempt_count %08x,"
" exited with %08x?\n", h - softirq_vec,
softirq_to_name[h - softirq_vec],
h->action, prev_count, preempt_count());
preempt_count() = prev_count;
} rcu_bh_qs(cpu);
}
h++;
pending >>= 1;
} while (pending); // Shut down the local CPU Hard interrupt on
local_irq_disable();
// Get bitmask
pending = local_softirq_pending();
if (pending && --max_restart)
goto restart; if (pending)
wakeup_softirqd(); lockdep_softirq_exit(); account_system_vtime(current);
// Add the soft interrupt counter to 1, Activate softinterrupt
_local_bh_enable();
}

6 ksoftirqd Kernel thread

6.1 ksoftirqd

In the kernel processing similar NET_RX_SOFTIRQ Soft interrupt of , If there are a lot of packets waiting to be processed . It's going to keep calling

__raise_softirq_irqoff(NET_RX_SOFTIRQ) Trigger soft interrupt repeatedly NET_RX_SOFTIRQ. Doing so will cause the user process to ” The problem of hunger “ ( Not available for a long time CPU).

To solve this problem, the kernel uses kernel threads ksoftirqd To handle self triggering more than 10 Second soft interrupt .

6.2 ksoftirqd The implementation of the

static int ksoftirqd(void * __bind_cpu)
{
//ksoftirqd Has the lowest priority (nice = 19)
set_user_nice(current, 19);
// take ksoftirqd Set to unfrozen
current->flags |= PF_NOFREEZE;
// Set up ksoftirqd Is interruptible
set_current_state(TASK_INTERRUPTIBLE); while (!kthread_should_stop()) {
// If there are no pending soft interrupts, then Scheduling other processes
if (!local_softirq_pending())
schedule(); __set_current_state(TASK_RUNNING); while (local_softirq_pending()) {
/* Preempt disable stops cpu going offline.
If already offline, we'll be on wrong CPU:
don't process */
// Turn off kernel preemption
preempt_disable();
// Handle soft interrupts
do_softirq();
// Turn on kernel preemption
preempt_enable();
//cond_resched() The purpose is to improve the real-time performance of the system , Give up on your own initiative cpu For higher priority tasks
cond_resched();
} set_current_state(TASK_INTERRUPTIBLE);
}
__set_current_state(TASK_RUNNING);
return 0;
}

Program 6-1 ksoftirqd Main function

out:
local_irq_enable();
return; softnet_break:
__get_cpu_var(netdev_rx_stat).time_squeeze++;
__raise_softirq_irqoff(NET_RX_SOFTIRQ);
goto out;

Program 6-2 net_rx_action

void wakeup_softirqd(void)
{
/* Interrupts are disabled: no need to stop preemption */
struct task_struct *tsk = __get_cpu_var(ksoftirqd); if (tsk && tsk->state != TASK_RUNNING)
wake_up_process(tsk);
}

Program 6-3 wakeup_softirqd

Unsolved problems

set_current_state and __set_current_state The difference between

PF_NOFREEZE

cond_resched()

Why is it do_softirq Turn off hardware interrupt when you start processing software interrupt

Reference resources

ULK

http://blog.csdn.net/hardy_2009/article/details/7383729 Description of kernel stack and interrupt stack

Linux More articles about kernel soft interrupt

  1. linux kernel -- Soft interrupt and tasklet

    Hardware interrupts usually need to be executed in the shortest time , If you put all the hardware interrupt related processing in the hardware interrupt handler , Then we can't achieve this goal . adopt linux Soft interrupt and tasklet, The hardware interrupt can be delayed in the processor ...

  2. [Linux kernel ] Soft interrupt 、tasklet、 Work queue

    from :http://www.cnblogs.com/li-hao/archive/2012/01/12/2321084.html Soft interrupt .tasklet And work queues are not Linux The mechanism that always exists in the kernel , ...

  3. [Linux kernel ] Soft interrupt and hard interrupt

    from :http://blog.csdn.net/zhangskd/article/details/21992933 Main contents of this paper : Hard interrupt / The principle and implementation of soft interrupt Kernel version :2.6.37 Author: ...

  4. Linux Soft interrupts in the kernel 、tasklet And work queues

    [TOC] This article is based on Linux2.6.32 Kernel version number . introduction Soft interrupt .tasklet And work queues are not Linux The mechanism that always exists in the kernel , It's made up of " The second half "(bottom ...

  5. elementary analysis linux The kernel timer Timer generation and sofirq Soft interrupt call flow ( from http://blog.chinaunix.net/uid-20564848-id-73480.html)

    elementary analysis linux The kernel timer Timer generation and sofirq Soft interrupt call flow mod_timer Added timer timer A call occurs in the soft interrupt of the kernel ,__run_timers Meeting spin_lock_irq(& ...

  6. elementary analysis linux The kernel timer Timer generation and sofirq Soft interrupt call flow 【 turn 】

    from :http://blog.chinaunix.net/uid-20564848-id-73480.html elementary analysis linux The kernel timer Timer generation and sofirq Soft interrupt call flow mod_time ...

  7. 《 In depth understanding of Linux kernel 》 Soft interrupt /tasklet/ Work queue

    Soft interrupt .tasklet And work queues are not Linux The mechanism that always exists in the kernel , It's made up of... In earlier versions of the kernel “ The second half ”(bottom half) Evolved . There are actually five mechanisms in the lower half , but 2.6 Version of the kernel , The second half and Ren ...

  8. grasp linux Kernel design idea ( 3、 ... and ): Soft interrupt in the lower part of the mechanism

    [ Copyright notice : Respect for the original . Reprint please keep the source :blog.csdn.net/shallnet, This article is for study and exchange only , Do not use for commercial purposes ]         The interrupt handler executes asynchronously , It interrupts other important code , It should be executed in ...

  9. linux Kernel analysis job 8: Understand the process scheduling timing, track and analyze the process of process scheduling and process switching

    1. The experiment purpose Select a system call (13 System call time With the exception of ), System call list , Use library functions API and C Code embedded assembly code, two ways to use the same system call Analyze the working process of assembly code calling system calling , In particular, the passing side of the parameter ...

  10. linux Kernel analysis job 5: analysis system_call Interrupt processing

    1. increase Menu Kernel command line Debug system calls . step : Delete menu git clone        (tab) make rootfs That's what we're going to do fork Function write Menu The effect of the system kernel , ...

Random recommendation

  1. shell in export Misunderstandings

    all the time , think shell In the script export The latter variable will affect the execution of this shell Environment variables in the terminal of . The concept of environmental variables is not shell Unique , It is linux What the process has in it ,shell The interpreter works like ...

  2. RadGrid Using skills : from RadGrid Get the value of the binding

    This article mainly introduces from RadGrid Get the value of the binding , Only applicable to Telerik RadControls for asp.net ajax. Access method RadGrid Store bound values in VIewState in , Even if View ...

  3. [ turn ]Linux In the system ‘dmesg’ Command to handle faults and collect system information 7 Usage

    'dmesg' Command display linux Ring buffer information of the kernel , We can get things like system architecture .cpu. Mounted hardware ,RAM A large amount of system information at multiple operation levels . When the computer starts , system kernel ( The core part of the operating system ) Will be loaded into ...

  4. Micro courses --Android--Android Developing learning systems

    Four components csdn The above website about Android learning materials http://blog.csdn.net/vanpersie_9987/article/details/53043590 It's a sin to spend money on it because you're too lazy , It took ...

  5. Learn more Redis(2): Persistence

    Preface In the last article , It introduces Redis Memory model , Start with this article , Will introduce in turn Redis High availability related knowledge —— Persistence . Copy ( And separation of reading and writing ). sentry . And cluster . This paper will first explain that the above-mentioned technologies solve the problem respectively Redis Gao Ke ...

  6. Web Storage and cookie

    Cookie The role of is to interact with the server , As HTTP Part of the norm , and Web Storage Just to be local “ Storage ” Data comes from ; Web Storage The concept and cookie be similar , The difference is that it's for a bigger size ...

  7. Pycharm in You are using pip version 10.0.1, however version 18.1 is available. You should consider upgrading via the &#39;python -m pip install --upgrade pip&#39; command.

    Today, when I was running the program, I saw : You are using pip version 10.0.1, however version 18.1 is available.You should conside ...

  8. Element Ui in table Realize the effect of table editing

    Mainly with css Realization .tb-edit .el-input, .tb-edit .el-input-number, .tb-edit .el-select { display: none; width: ...

  9. python Callback function , The simplest example

    The English definition of callback : A callback is a function that is passed as an argument to another function and is executed ...

  10. Nine configparser modular

    The configuration file is as follows : # notes 1 ; notes 2 [section1] k1 = v1 k2:v2 user=egon age=18 is_admin=true salary=31 [section2] k1 ...