RCU-4——不可抢占RCU代码分析

发布时间 2023-04-27 21:07:35作者: Hello-World3

基于 Linux-5.10

一、不可抢占RCU

1. 不可抢占RCU不允许进程在读端临界区被其它进程抢占,使用函数 rcu_read_lock_sched()/rcu_read_unlock_sched() 标记读临界区。前者禁止内核抢占,后者开启内核抢占。

static inline void rcu_read_lock_sched(void) //include/linux/rcupdate.h
{
    preempt_disable();
}

static inline void rcu_read_unlock_sched(void)
{
    preempt_enable();
}

2. 不可抢占RCU通过以下事件观察到静止状态

(1) 进程调度器调度进程。因为不可抢占RCU读临界区禁止内核抢占,所以进程调度器不会在读临界区调度进程,如果调度了进程,那么一定不在读临界区。

(2) 当前进程正在用户模式下运行。

(3) 处理器空闲,正在执行idle线程。

静态的观察位置1:

__schedule(bool preempt) //sched/core.c
    rcu_note_context_switch(preempt); //tree_plugin.h local_irq_disable()后调用,这个函数也要求必须要关中断调用
        rcu_qs();

TODO

 

二、加速版不可抢占RCU

1. 加速版不可抢占RCU(RCU-bh)使用 rcu_read_lock_bh()/rcu_read_unlock_bh() 标记读端临界区,前者禁止软中断,后者开启软中断。

static inline void rcu_read_lock_bh(void)
{
    local_bh_disable();
    ...
}

static inline void rcu_read_unlock_bh(void)
{
    ...
    local_bh_enable();
}

2. 加速版不可抢占RCU通过以下事件观察到静止状态:

(1) 执行完软中断。因为RCU-bh的读端临界区是禁止软中断的,所以进程在读端临界区是不会被软中断抢占。

(2) 当前进程在用户模式下运行。

(3) 处理器空闲,正在执行idle线程。

(4) 处理器没有执行软中断或禁止软中断的代码区域。


3. 检查静止状态的时机

(1) 执行完一轮软中断后,禁止硬中断之前,调用 rcu_qs() 记录静止状态:

irq_exit_rcu
irq_exit
    __irq_exit_rcu
        invoke_softirq
            do_softirq_own_stack
                __do_softirq //softirq.c
                    rcu_softirq_qs //tree.c
                        rcu_qs //tree_plugin.h

(2) tick中断中会检查 

update_process_times

TODO