ARM10C 71주차 후기
일시 : 2014.09.27 (71주차)
모임명 : NAVER개발자커뮤니티지원_IAMROOT.ORG_10차ARM-C
장소 : 토즈 타워점
장소지원 : NAVER 개발자 커뮤니티 지원 프로그램
참여인원 : 3명
스터디 진도 :
main.c::start_kernel()
- rcu_init()을 분석합니다.
- start_kernel()부터 rcu_init() 전에 어떤 일을 했는지 간추려서 보겠습니다.
asmlinkage void __init start_kernel(void)
{
char * command_line;
extern const struct kernel_param __start___param[], __stop___param[];
...
local_irq_disable();
// IRQ를 disable한다.
early_boot_irqs_disabled = true;
boot_cpu_init()
// 현재 cpu(core id)를 얻어서 cpu_XXX_bits[] 의 cpu를 셋한다.
page_address_init();
// 128개의 page_address_htable 배열을 초기화
pr_notice("%s", linux_banner);
// 배너:
// Linux version 2.6.37_DM385_IPNC_3.50.00
// (a0875405@bangvideoapps01) (gcc version 4.5.3 20110311
// (prerelease) (GCC) ) #1 Fri Dec 21 17:27:08 IST 2012
setup_arch(&command_line);
// ARM 아키텍쳐에 맞게 초기화한다.
setup_nr_cpu_ids();
setup_per_cpu_areas();
// pcpu 구조체를 만들어 줌 (mm/percpu.c)
smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
// boot cpu 0의 pcpu 영역의 base주소를 core register에 설정해줌
...
pidhash_init();
// pidhash의 크기를 16kB만큼 할당 받고 4096개의 hash list를 만듬
vfs_caches_init_early();
// Dentry cache, Inode-cache용 hash를 위한 메모리 공간을 각각 512kB, 256kB만큼 할당 받고,
// 131072, 65536개 만큼 hash table을 각각 만듬
...
mm_init();
// buddy와 slab 을 활성화 하고 기존 할당 받은 bootmem 은 buddy,
// pcpu 메모리, vmlist 는 slab으로 이관
sched_init();
// scheduler가 사용하는 자료 구조 초기화, idle_threads를 init_task로 세팅
/*
* Disable preemption - early bootup scheduling is extremely
* fragile until we cpu_idle() for the first time.
*/
preempt_disable();
// preempt count를 증가시켜 preemption 못하도록 막음
// irqs_disabled(): 1
if (WARN(!irqs_disabled(), "Interrupts were enabled *very* early, fixing it\n"))
local_irq_disable();
idr_init_cache();
// integer ID management로 사용하는 idr_layer_cache에 kmem_cache#21 을 생성 및 초기화 후 할당
rcu_init();
- mm_init()에서 buddy와 slab을 활성화하고 sched_init()을 실행한다.
- sched_init()에서 rq를 초기화하고 // scheduler_running: 1
- integer ID management로 사용하는 idr_layer_cache에 kmem_cache#21 을 생성 및 초기화 후 할당 *
tree.c::rcu_init()
- rcu_bootup_announce();
- "Preemptible hierarchical RCU implementation." 출력
- rcu_init_geometry();
- // jiffies_till_first_fqs: 1
- // jiffies_till_next_fqs: 1
- rcu_init_one(&rcu_bh_state, &rcu_bh_data);
- // (&rcu_bh_state)->levelcnt[0]: 1
- // (&rcu_bh_state)->levelspread[0]: 4
- // &((&rcu_bh_state)->level[0])->lock 사용한 spinlock 초기화
- // &((&rcu_bh_state)->level[0])->fqslock 사용한 spinlock 초기화
- // ((&rcu_bh_state)->level[0])->completed: 0xfffffed4
- // ((&rcu_bh_state)->level[0])->qsmask: 0
- // ((&rcu_bh_state)->level[0])->qsmaskinit: 0
- // ((&rcu_bh_state)->level[0])->grplo: 0
- // ((&rcu_bh_state)->level[0])->grphi: 3
- // ((&rcu_bh_state)->level[0])->gpnum: 0
- // ((&rcu_bh_state)->level[0])->grpmask: 0
- // ((&rcu_bh_state)->level[0])->parent: NULL
- // ((&rcu_bh_state)->level[0])->level: 0
- // &((&rcu_bh_state)->level[0])->blkd_tasks 을 사용한 list 초기화
- // (&rcu_bh_state)->rda: &rcu_bh_data
- // &(&(&rcu_bh_state)->gp_wq)->lock을 사용한 spinlock 초기화
- // &(&(&rcu_bh_state)->gp_wq)->task_list를 사용한 list 초기화
- // (&(&rcu_bh_state)->wakeup_work)->flags: 0
- // (&(&rcu_bh_state)->wakeup_work)->func: rsp_wakeup
- //
- // (&rcu_bh_state)->level[0]
- //
- // pcp0->mynode: (&rcu_bh_state)->level[0]
- // pcp1->mynode: (&rcu_bh_state)->level[0]
- // pcp2->mynode: (&rcu_bh_state)->level[0]
- // pcp3->mynode: (&rcu_bh_state)->level[0]
- //
- // pcp0->grpmask: 1
- // pcp0->nxtlist: NULL
- // pcp0->nxttail[0...3]: [pcp0] &(&rcu_bh_data)->nxtlist
- // pcp0->qlen_lazy: 0
- // pcp0->qlen: 0
- // pcp0->dynticks: [pcp0] &rcu_dynticks
- // pcp0->cpu: 0
- // pcp0->rsp: &rcu_bh_state
- // pcp1->grpmask: 2
- // pcp1->nxtlist: NULL
- // pcp1->nxttail[0...3]: [pcp0] &(&rcu_bh_data)->nxtlist
- // pcp1->qlen_lazy: 0
- // pcp1->qlen: 0
- // pcp1->dynticks: [pcp1] &rcu_dynticks
- // pcp1->cpu: 1
- // pcp1->rsp: &rcu_bh_state
- // pcp2->grpmask: 4
- // pcp2->nxtlist: NULL
- // pcp2->nxttail[0...3]: [pcp2] &(&rcu_bh_data)->nxtlist
- // pcp2->qlen_lazy: 0
- // pcp2->qlen: 0
- // pcp2->dynticks: [pcp2] &rcu_dynticks
- // pcp2->cpu: 2
- // pcp2->rsp: &rcu_bh_state
- // pcp3->grpmask: 8
- // pcp3->nxtlist: NULL
- // pcp3->nxttail[0...3]: [pcp3] &(&rcu_bh_data)->nxtlist
- // pcp3->qlen_lazy: 0
- // pcp3->qlen: 0
- // pcp3->dynticks: [pcp3] &rcu_dynticks
- // pcp3->cpu: 3
- // pcp3->rsp: &rcu_bh_state
- //
- // rcu_struct_flavors에 (&rcu_bh_state)->flavors를 list 추가
- rcu_init_one(&rcu_sched_state, &rcu_sched_data);
- // (&rcu_sched_state)->levelcnt[0]: 1
- // (&rcu_sched_state)->levelspread[0]: 4
- // &((&rcu_sched_state)->level[0])->lock 사용한 spinlock 초기화
- // &((&rcu_sched_state)->level[0])->fqslock 사용한 spinlock 초기화
- // ((&rcu_sched_state)->level[0])->completed: 0xfffffed4
- // ((&rcu_sched_state)->level[0])->qsmask: 0
- // ((&rcu_sched_state)->level[0])->qsmaskinit: 0
- // ((&rcu_sched_state)->level[0])->grplo: 0
- // ((&rcu_sched_state)->level[0])->grphi: 3
- // ((&rcu_sched_state)->level[0])->gpnum: 0
- // ((&rcu_sched_state)->level[0])->grpmask: 0
- // ((&rcu_sched_state)->level[0])->parent: NULL
- // ((&rcu_sched_state)->level[0])->level: 0
- // &((&rcu_sched_state)->level[0])->blkd_tasks 을 사용한 list 초기화
- //
- // (&rcu_sched_state)->rda: &rcu_sched_data
- // &(&(&rcu_sched_state)->gp_wq)->lock을 사용한 spinlock 초기화
- // &(&(&rcu_sched_state)->gp_wq)->task_list를 사용한 list 초기화
- // (&(&rcu_sched_state)->wakeup_work)->flags: 0
- // (&(&rcu_sched_state)->wakeup_work)->func: rsp_wakeup
- //
- // (&rcu_sched_state)->level[0]
- //
- // pcp0->mynode: (&rcu_sched_state)->level[0]
- // pcp1->mynode: (&rcu_sched_state)->level[0]
- // pcp2->mynode: (&rcu_sched_state)->level[0]
- // pcp3->mynode: (&rcu_sched_state)->level[0]
- //
- // pcp0->grpmask: 1
- // pcp0->nxtlist: NULL
- // pcp0->nxttail[0...3]: [pcp0] &(&rcu_sched_data)->nxtlist
- // pcp0->qlen_lazy: 0
- // pcp0->qlen: 0
- // pcp0->dynticks: [pcp0] &rcu_dynticks
- // pcp0->cpu: 0
- // pcp0->rsp: &rcu_sched_state
- // pcp1->grpmask: 2
- // pcp1->nxtlist: NULL
- // pcp1->nxttail[0...3]: [pcp0] &(&rcu_sched_data)->nxtlist
- // pcp1->qlen_lazy: 0
- // pcp1->qlen: 0
- // pcp1->dynticks: [pcp1] &rcu_dynticks
- // pcp1->cpu: 1
- // pcp1->rsp: &rcu_sched_state
- // pcp2->grpmask: 4
- // pcp2->nxtlist: NULL
- // pcp2->nxttail[0...3]: [pcp2] &(&rcu_sched_data)->nxtlist
- // pcp2->qlen_lazy: 0
- // pcp2->qlen: 0
- // pcp2->dynticks: [pcp2] &rcu_dynticks
- // pcp2->cpu: 2
- // pcp2->rsp: &rcu_sched_state
- // pcp3->grpmask: 8
- // pcp3->nxtlist: NULL
- // pcp3->nxttail[0...3]: [pcp3] &(&rcu_sched_data)->nxtlist
- // pcp3->qlen_lazy: 0
- // pcp3->qlen: 0
- // pcp3->dynticks: [pcp3] &rcu_dynticks
- // pcp3->cpu: 3
- // pcp3->rsp: &rcu_sched_state
- //
- // rcu_struct_flavors에 (&rcu_sched_state)->flavors를 list 추가
- open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
- // softirq_vec[9].action: rcu_process_callbacks
- cpu_notifier(rcu_cpu_notify, 0);
- // (&cpu_chain)->head: rcu_cpu_notify_nb 포인터 대입
- // (&rcu_cpu_notify_nb)->next은 (&sched_ilb_notifier_nb)->next로 대입
- pm_notifier(rcu_pm_notify, 0);
- // (&pm_chain_head)->head: rcu_pm_notify_nb 포인터 대입
- // n->next: (&rcu_pm_notify_nb)->next: NULL
- for_each_online_cpu(cpu)
// ARM10C 20140920
void __init rcu_init(void)
{
int cpu;
rcu_bootup_announce();
rcu_init_geometry();
// jiffies_till_first_fqs: 1
// jiffies_till_next_fqs: 1
// 2014/09/20 종료
// 2014/09/27 시작
rcu_init_one(&rcu_bh_state, &rcu_bh_data);
// (&rcu_bh_state)->levelcnt[0]: 1
// (&rcu_bh_state)->levelspread[0]: 4
// &((&rcu_bh_state)->level[0])->lock 사용한 spinlock 초기화
// &((&rcu_bh_state)->level[0])->fqslock 사용한 spinlock 초기화
// ((&rcu_bh_state)->level[0])->completed: 0xfffffed4
// ((&rcu_bh_state)->level[0])->qsmask: 0
// ((&rcu_bh_state)->level[0])->qsmaskinit: 0
// ((&rcu_bh_state)->level[0])->grplo: 0
// ((&rcu_bh_state)->level[0])->grphi: 3
// ((&rcu_bh_state)->level[0])->gpnum: 0
// ((&rcu_bh_state)->level[0])->grpmask: 0
// ((&rcu_bh_state)->level[0])->parent: NULL
// ((&rcu_bh_state)->level[0])->level: 0
// &((&rcu_bh_state)->level[0])->blkd_tasks 을 사용한 list 초기화
//
// (&rcu_bh_state)->rda: &rcu_bh_data
// &(&(&rcu_bh_state)->gp_wq)->lock을 사용한 spinlock 초기화
// &(&(&rcu_bh_state)->gp_wq)->task_list를 사용한 list 초기화
// (&(&rcu_bh_state)->wakeup_work)->flags: 0
// (&(&rcu_bh_state)->wakeup_work)->func: rsp_wakeup
//
// (&rcu_bh_state)->level[0]
//
// [pcp0] (&rcu_bh_data)->mynode: (&rcu_bh_state)->level[0]
// [pcp1] (&rcu_bh_data)->mynode: (&rcu_bh_state)->level[0]
// [pcp2] (&rcu_bh_data)->mynode: (&rcu_bh_state)->level[0]
// [pcp3] (&rcu_bh_data)->mynode: (&rcu_bh_state)->level[0]
//
// [pcp0] (&rcu_bh_data)->grpmask: 1
// [pcp0] (&rcu_bh_data)->nxtlist: NULL
// [pcp0] (&rcu_bh_data)->nxttail[0...3]: [pcp0] &(&rcu_bh_data)->nxtlist
// [pcp0] (&rcu_bh_data)->qlen_lazy: 0
// [pcp0] (&rcu_bh_data)->qlen: 0
// [pcp0] (&rcu_bh_data)->dynticks: [pcp0] &rcu_dynticks
// [pcp0] (&rcu_bh_data)->cpu: 0
// [pcp0] (&rcu_bh_data)->rsp: &rcu_bh_state
//
// rcu_struct_flavors에 (&rcu_bh_state)->flavors를 list 추가
rcu_init_one(&rcu_sched_state, &rcu_sched_data);
// (&rcu_sched_state)->levelcnt[0]: 1
// (&rcu_sched_state)->levelspread[0]: 4
// &((&rcu_sched_state)->level[0])->lock 사용한 spinlock 초기화
// &((&rcu_sched_state)->level[0])->fqslock 사용한 spinlock 초기화
// ((&rcu_sched_state)->level[0])->completed: 0xfffffed4
// ((&rcu_sched_state)->level[0])->qsmask: 0
// ((&rcu_sched_state)->level[0])->qsmaskinit: 0
// ((&rcu_sched_state)->level[0])->grplo: 0
// ((&rcu_sched_state)->level[0])->grphi: 3
// ((&rcu_sched_state)->level[0])->gpnum: 0
// ((&rcu_sched_state)->level[0])->grpmask: 0
// ((&rcu_sched_state)->level[0])->parent: NULL
// ((&rcu_sched_state)->level[0])->level: 0
// &((&rcu_sched_state)->level[0])->blkd_tasks 을 사용한 list 초기화
//
// (&rcu_sched_state)->rda: &rcu_sched_data
// &(&(&rcu_sched_state)->gp_wq)->lock을 사용한 spinlock 초기화
// &(&(&rcu_sched_state)->gp_wq)->task_list를 사용한 list 초기화
// (&(&rcu_sched_state)->wakeup_work)->flags: 0
// (&(&rcu_sched_state)->wakeup_work)->func: rsp_wakeup
//
// (&rcu_sched_state)->level[0]
//
// [pcp0] (&rcu_sched_data)->mynode: (&rcu_sched_state)->level[0]
// [pcp1] (&rcu_sched_data)->mynode: (&rcu_sched_state)->level[0]
// [pcp2] (&rcu_sched_data)->mynode: (&rcu_sched_state)->level[0]
// [pcp3] (&rcu_sched_data)->mynode: (&rcu_sched_state)->level[0]
//
// [pcp0] (&rcu_sched_data)->grpmask: 1
// [pcp0] (&rcu_sched_data)->nxtlist: NULL
// [pcp0] (&rcu_sched_data)->nxttail[0...3]: [pcp0] &(&rcu_sched_data)->nxtlist
// [pcp0] (&rcu_sched_data)->qlen_lazy: 0
// [pcp0] (&rcu_sched_data)->qlen: 0
// [pcp0] (&rcu_sched_data)->dynticks: [pcp0] &rcu_dynticks
// [pcp0] (&rcu_sched_data)->cpu: 0
// [pcp0] (&rcu_sched_data)->rsp: &rcu_sched_state
// [pcp1] (&rcu_sched_data)->grpmask: 2
// [pcp1] (&rcu_sched_data)->nxtlist: NULL
// [pcp1] (&rcu_sched_data)->nxttail[0...3]: [pcp0] &(&rcu_sched_data)->nxtlist
// [pcp1] (&rcu_sched_data)->qlen_lazy: 0
// [pcp1] (&rcu_sched_data)->qlen: 0
// [pcp1] (&rcu_sched_data)->dynticks: [pcp1] &rcu_dynticks
// [pcp1] (&rcu_sched_data)->cpu: 1
// [pcp1] (&rcu_sched_data)->rsp: &rcu_sched_state
// [pcp2] (&rcu_sched_data)->grpmask: 4
// [pcp2] (&rcu_sched_data)->nxtlist: NULL
// [pcp2] (&rcu_sched_data)->nxttail[0...3]: [pcp2] &(&rcu_sched_data)->nxtlist
// [pcp2] (&rcu_sched_data)->qlen_lazy: 0
// [pcp2] (&rcu_sched_data)->qlen: 0
// [pcp2] (&rcu_sched_data)->dynticks: [pcp2] &rcu_dynticks
// [pcp2] (&rcu_sched_data)->cpu: 2
// [pcp2] (&rcu_sched_data)->rsp: &rcu_sched_state
// [pcp3] (&rcu_sched_data)->grpmask: 8
// [pcp3] (&rcu_sched_data)->nxtlist: NULL
// [pcp3] (&rcu_sched_data)->nxttail[0...3]: [pcp3] &(&rcu_sched_data)->nxtlist
// [pcp3] (&rcu_sched_data)->qlen_lazy: 0
// [pcp3] (&rcu_sched_data)->qlen: 0
// [pcp3] (&rcu_sched_data)->dynticks: [pcp3] &rcu_dynticks
// [pcp3] (&rcu_sched_data)->cpu: 3
// [pcp3] (&rcu_sched_data)->rsp: &rcu_sched_state
//
// rcu_struct_flavors에 (&rcu_sched_state)->flavors를 list 추가
__rcu_init_preempt();
// __rcu_init_preempt 한일:
// (&rcu_preempt_state)->levelcnt[0]: 1
// (&rcu_preempt_state)->levelspread[0]: 4
// &((&rcu_preempt_state)->level[0])->lock 사용한 spinlock 초기화
// &((&rcu_preempt_state)->level[0])->fqslock 사용한 spinlock 초기화
// ((&rcu_preempt_state)->level[0])->completed: 0xfffffed4
// ((&rcu_preempt_state)->level[0])->qsmask: 0
// ((&rcu_preempt_state)->level[0])->qsmaskinit: 0
// ((&rcu_preempt_state)->level[0])->grplo: 0
// ((&rcu_preempt_state)->level[0])->grphi: 3
// ((&rcu_preempt_state)->level[0])->gpnum: 0
// ((&rcu_preempt_state)->level[0])->grpmask: 0
// ((&rcu_preempt_state)->level[0])->parent: NULL
// ((&rcu_preempt_state)->level[0])->level: 0
// &((&rcu_preempt_state)->level[0])->blkd_tasks 을 사용한 list 초기화
//
// (&rcu_preempt_state)->rda: &rcu_preempt_data
// &(&(&rcu_preempt_state)->gp_wq)->lock을 사용한 spinlock 초기화
// &(&(&rcu_preempt_state)->gp_wq)->task_list를 사용한 list 초기화
// (&(&rcu_preempt_state)->wakeup_work)->flags: 0
// (&(&rcu_preempt_state)->wakeup_work)->func: rsp_wakeup
//
// (&rcu_preempt_state)->level[0]
//
// [pcp0] (&rcu_preempt_data)->mynode: (&rcu_preempt_state)->level[0]
// [pcp1] (&rcu_preempt_data)->mynode: (&rcu_preempt_state)->level[0]
// [pcp2] (&rcu_preempt_data)->mynode: (&rcu_preempt_state)->level[0]
// [pcp3] (&rcu_preempt_data)->mynode: (&rcu_preempt_state)->level[0]
//
// [pcp0] (&rcu_preempt_data)->grpmask: 1
// [pcp0] (&rcu_preempt_data)->nxtlist: NULL
// [pcp0] (&rcu_preempt_data)->nxttail[0...3]: [pcp0] &(&rcu_preempt_data)->nxtlist
// [pcp0] (&rcu_preempt_data)->qlen_lazy: 0
// [pcp0] (&rcu_preempt_data)->qlen: 0
// [pcp0] (&rcu_preempt_data)->dynticks: [pcp0] &rcu_dynticks
// [pcp0] (&rcu_preempt_data)->cpu: 0
// [pcp0] (&rcu_preempt_data)->rsp: &rcu_preempt_state
// [pcp1] (&rcu_preempt_data)->grpmask: 2
// [pcp1] (&rcu_preempt_data)->nxtlist: NULL
// [pcp1] (&rcu_preempt_data)->nxttail[0...3]: [pcp0] &(&rcu_preempt_data)->nxtlist
// [pcp1] (&rcu_preempt_data)->qlen_lazy: 0
// [pcp1] (&rcu_preempt_data)->qlen: 0
// [pcp1] (&rcu_preempt_data)->dynticks: [pcp1] &rcu_dynticks
// [pcp1] (&rcu_preempt_data)->cpu: 1
// [pcp1] (&rcu_preempt_data)->rsp: &rcu_preempt_state
// [pcp2] (&rcu_preempt_data)->grpmask: 4
// [pcp2] (&rcu_preempt_data)->nxtlist: NULL
// [pcp2] (&rcu_preempt_data)->nxttail[0...3]: [pcp2] &(&rcu_preempt_data)->nxtlist
// [pcp2] (&rcu_preempt_data)->qlen_lazy: 0
// [pcp2] (&rcu_preempt_data)->qlen: 0
// [pcp2] (&rcu_preempt_data)->dynticks: [pcp2] &rcu_dynticks
// [pcp2] (&rcu_preempt_data)->cpu: 2
// [pcp2] (&rcu_preempt_data)->rsp: &rcu_preempt_state
// [pcp3] (&rcu_preempt_data)->grpmask: 8
// [pcp3] (&rcu_preempt_data)->nxtlist: NULL
// [pcp3] (&rcu_preempt_data)->nxttail[0...3]: [pcp3] &(&rcu_preempt_data)->nxtlist
// [pcp3] (&rcu_preempt_data)->qlen_lazy: 0
// [pcp3] (&rcu_preempt_data)->qlen: 0
// [pcp3] (&rcu_preempt_data)->dynticks: [pcp3] &rcu_dynticks
// [pcp3] (&rcu_preempt_data)->cpu: 3
// [pcp3] (&rcu_preempt_data)->rsp: &rcu_preempt_state
//
// rcu_struct_flavors에 (&rcu_preempt_state)->flavors를 list 추가
// RCU_SOFTIRQ: 9,
open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
// open_softirq에서 한일:
// softirq_vec[9].action: rcu_process_callbacks
/*
* We don't need protection against CPU-hotplug here because
* this is called early in boot, before either interrupts
* or the scheduler are operational.
*/
cpu_notifier(rcu_cpu_notify, 0);
// cpu_notifier에서 한일:
// (&cpu_chain)->head: rcu_cpu_notify_nb 포인터 대입
// (&rcu_cpu_notify_nb)->next은 (&sched_ilb_notifier_nb)->next로 대입
pm_notifier(rcu_pm_notify, 0);
// pm_notifier에서 한일:
// (&pm_chain_head)->head: rcu_pm_notify_nb 포인터 대입
// n->next: (&rcu_pm_notify_nb)->next: NULL
for_each_online_cpu(cpu)
// for ((cpu) = -1; (cpu) = cpumask_next((cpu), (cpu_online_mask)), (cpu) < nr_cpu_ids; )
// CPU_UP_PREPARE: 0x0003, cpu: 0
// rcu_cpu_notify(NULL, 0x0003, 0): NOTIFY_OK: 0x0001
// CPU_UP_PREPARE: 0x0003, cpu: 1
// rcu_cpu_notify(NULL, 0x0003, 1): NOTIFY_OK: 0x0001
// CPU_UP_PREPARE: 0x0003, cpu: 2
// rcu_cpu_notify(NULL, 0x0003, 2): NOTIFY_OK: 0x0001
// CPU_UP_PREPARE: 0x0003, cpu: 3
// rcu_cpu_notify(NULL, 0x0003, 3): NOTIFY_OK: 0x0001
rcu_cpu_notify(NULL, CPU_UP_PREPARE, (void *)(long)cpu);
// rcu_cpu_notify에서 한일:
// [pcp0...3] (&rcu_bh_data)->beenonline: 1
// [pcp0...3] (&rcu_bh_data)->preemptible: 0
// [pcp0...3] (&rcu_bh_data)->len_last_fqs_check: 0
// [pcp0...3] (&rcu_bh_data)->n_force_qs_snap: 0
// [pcp0...3] (&rcu_bh_data)->blimit: 10
// [pcp0...3] (&rcu_bh_data)->nxtlist: NULL
// [pcp0...3] (&rcu_bh_data)->nxttail[0...3]: [pcp0...3] &(&rcu_bh_data)->nxtlist
// [pcp0...3] (&rcu_bh_data)->dynticks->dynticks_nesting: 0x140000000000000
// [pcp0...3] (&rcu_bh_data)->dynticks->dynticks: 1
// [pcp0...3] ((&rcu_bh_state)->level[0])->qsmaskinit: [pcp0] 1, [pcp1] 2, [pcp2] 4, [pcp3] 8
// [pcp0...3] (&rcu_bh_data)->gpnum: 0xfffffed4
// [pcp0...3] (&rcu_bh_data)->passed_quiesce: 0
// [pcp0...3] (&rcu_bh_data)->qs_pending: 0
//
// [pcp0...3] (&rcu_sched_data)->beenonline: 1
// [pcp0...3] (&rcu_sched_data)->preemptible: 0
// [pcp0...3] (&rcu_sched_data)->len_last_fqs_check: 0
// [pcp0...3] (&rcu_sched_data)->n_force_qs_snap: 0
// [pcp0...3] (&rcu_sched_data)->blimit: 10
// [pcp0...3] (&rcu_sched_data)->nxtlist: NULL
// [pcp0...3] (&rcu_sched_data)->nxttail[0...3]: [pcp0...3] &(&rcu_sched_data)->nxtlist
// [pcp0...3] (&rcu_sched_data)->dynticks->dynticks_nesting: 0x140000000000000
// [pcp0...3] (&rcu_sched_data)->dynticks->dynticks: 1
// [pcp0...3] ((&rcu_sched_state)->level[0])->qsmaskinit: [pcp0] 1, [pcp1] 2, [pcp2] 4, [pcp3] 8
// [pcp0...3] (&rcu_sched_data)->gpnum: 0xfffffed4
// [pcp0...3] (&rcu_sched_data)->passed_quiesce: 0
// [pcp0...3] (&rcu_sched_data)->qs_pending: 0
//
// [pcp0...3] (&rcu_preempt_data)->beenonline: 1
// [pcp0...3] (&rcu_preempt_data)->preemptible: 1
// [pcp0...3] (&rcu_preempt_data)->len_last_fqs_check: 0
// [pcp0...3] (&rcu_preempt_data)->n_force_qs_snap: 0
// [pcp0...3] (&rcu_preempt_data)->blimit: 10
// [pcp0...3] (&rcu_preempt_data)->nxtlist: NULL
// [pcp0...3] (&rcu_preempt_data)->nxttail[0...3]: [pcp0...3] &(&rcu_preempt_data)->nxtlist
// [pcp0...3] (&rcu_preempt_data)->dynticks->dynticks_nesting: 0x140000000000000
// [pcp0...3] (&rcu_preempt_data)->dynticks->dynticks: 1
// [pcp0...3] ((&rcu_preempt_state)->level[0])->qsmaskinit: [pcp0] 1, [pcp1] 2, [pcp2] 4, [pcp3] 8
// [pcp0...3] (&rcu_preempt_data)->gpnum: 0xfffffed4
// [pcp0...3] (&rcu_preempt_data)->passed_quiesce: 0
// [pcp0...3] (&rcu_preempt_data)->qs_pending: 0
// 2014/09/27 종료
}
tree_plugin.h::rcu_bootup_announce();
// ARM10C 20140920
static void __init rcu_bootup_announce(void)
{
pr_info("Preemptible hierarchical RCU implementation.\n");
rcu_bootup_announce_oddness();
}
tree_plugin.h::rcu_bootup_annouce_oddness()
// ARM10C 20140920
static void __init rcu_bootup_announce_oddness(void)
{
#ifdef CONFIG_RCU_TRACE // CONFIG_RCU_TRACE=n
pr_info("\tRCU debugfs-based tracing is enabled.\n");
#endif
// CONFIG_64BIT=n, CONFIG_RCU_FANOUT=32
#if (defined(CONFIG_64BIT) && CONFIG_RCU_FANOUT != 64) || (!defined(CONFIG_64BIT) && CONFIG_RCU_FANOUT != 32)
pr_info("\tCONFIG_RCU_FANOUT set to non-default value of %d\n",
CONFIG_RCU_FANOUT);
#endif
#ifdef CONFIG_RCU_FANOUT_EXACT // CONFIG_RCU_FANOUT_EXACT=n
pr_info("\tHierarchical RCU autobalancing is disabled.\n");
#endif
#ifdef CONFIG_RCU_FAST_NO_HZ // CONFIG_RCU_FAST_NO_HZ=n
pr_info("\tRCU dyntick-idle grace-period acceleration is enabled.\n");
#endif
#ifdef CONFIG_PROVE_RCU // CONFIG_PROVE_RCU=n
pr_info("\tRCU lockdep checking is enabled.\n");
#endif
#ifdef CONFIG_RCU_TORTURE_TEST_RUNNABLE // CONFIG_RCU_TORTURE_TEST_RUNNABLE=n
pr_info("\tRCU torture testing starts during boot.\n");
#endif
// CONFIG_TREE_PREEMPT_RCU=y, CONFIG_RCU_CPU_STALL_VERBOSE=y
#if defined(CONFIG_TREE_PREEMPT_RCU) && !defined(CONFIG_RCU_CPU_STALL_VERBOSE)
pr_info("\tDump stacks of tasks blocking RCU-preempt GP.\n");
#endif
#if defined(CONFIG_RCU_CPU_STALL_INFO) // CONFIG_RCU_CPU_STALL_INFO=n
pr_info("\tAdditional per-CPU info printed with stalls.\n");
#endif
#if NUM_RCU_LVL_4 != 0 // NUM_RCU_LVL_4: 0
pr_info("\tFour-level hierarchy is enabled.\n");
#endif
// rcu_fanout_leaf: 16, CONFIG_RCU_FANOUT_LEAF: 16
if (rcu_fanout_leaf != CONFIG_RCU_FANOUT_LEAF)
pr_info("\tBoot-time adjustment of leaf fanout to %d.\n", rcu_fanout_leaf);
// nr_cpu_ids: 4, NR_CPUS: 4
if (nr_cpu_ids != NR_CPUS)
pr_info("\tRCU restricting CPUs from NR_CPUS=%d to nr_cpu_ids=%d.\n", NR_CPUS, nr_cpu_ids);
#ifdef CONFIG_RCU_NOCB_CPU // CONFIG_RCU_NOCB_CPU=n
#ifndef CONFIG_RCU_NOCB_CPU_NONE // CONFIG_RCU_NOCB_CPU_NONE=n
if (!have_rcu_nocb_mask) {
zalloc_cpumask_var(&rcu_nocb_mask, GFP_KERNEL);
have_rcu_nocb_mask = true;
}
#ifdef CONFIG_RCU_NOCB_CPU_ZERO // CONFIG_RCU_NOCB_CPU_ZERO=n
pr_info("\tOffload RCU callbacks from CPU 0\n");
cpumask_set_cpu(0, rcu_nocb_mask);
#endif /* #ifdef CONFIG_RCU_NOCB_CPU_ZERO */
#ifdef CONFIG_RCU_NOCB_CPU_ALL // CONFIG_RCU_NOCB_CPU_ALL=n
pr_info("\tOffload RCU callbacks from all CPUs\n");
cpumask_copy(rcu_nocb_mask, cpu_possible_mask);
#endif /* #ifdef CONFIG_RCU_NOCB_CPU_ALL */
#endif /* #ifndef CONFIG_RCU_NOCB_CPU_NONE */
if (have_rcu_nocb_mask) {
if (!cpumask_subset(rcu_nocb_mask, cpu_possible_mask)) {
pr_info("\tNote: kernel parameter 'rcu_nocbs=' contains nonexistent CPUs.\n");
cpumask_and(rcu_nocb_mask, cpu_possible_mask,
rcu_nocb_mask);
}
cpulist_scnprintf(nocb_buf, sizeof(nocb_buf), rcu_nocb_mask);
pr_info("\tOffload RCU callbacks from CPUs: %s.\n", nocb_buf);
if (rcu_nocb_poll)
pr_info("\tPoll for callbacks from no-CBs CPUs.\n");
}
#endif /* #ifdef CONFIG_RCU_NOCB_CPU */
}
rcu_init_geometry();
- rcu_init_geometry에서 한일:
- // jiffies_till_first_fqs: 1
- // jiffies_till_next_fqs: 1
// ARM10C 20140920
static void __init rcu_init_geometry(void)
{
ulong d;
int i;
int j;
// nr_cpu_ids: 4
int n = nr_cpu_ids;
// n: 4
// MAX_RCU_LVLS: 4
int rcu_capacity[MAX_RCU_LVLS + 1];
/*
* Initialize any unspecified boot parameters.
* The default values of jiffies_till_first_fqs and
* jiffies_till_next_fqs are set to the RCU_JIFFIES_TILL_FORCE_QS
* value, which is a function of HZ, then adding one for each
* RCU_JIFFIES_FQS_DIV CPUs that might be on the system.
*/
// RCU_JIFFIES_TILL_FORCE_QS: 1, nr_cpu_ids: 4, RCU_JIFFIES_FQS_DIV: 256
d = RCU_JIFFIES_TILL_FORCE_QS + nr_cpu_ids / RCU_JIFFIES_FQS_DIV;
// d: 1
// jiffies_till_first_fqs: 0xFFFFFFFF, ULONG_MAX: 0xFFFFFFFF
if (jiffies_till_first_fqs == ULONG_MAX)
// d: 1
jiffies_till_first_fqs = d;
// jiffies_till_first_fqs: 1
// jiffies_till_next_fqs: 0xFFFFFFFF, ULONG_MAX: 0xFFFFFFFF
if (jiffies_till_next_fqs == ULONG_MAX)
// d: 1
jiffies_till_next_fqs = d;
// jiffies_till_next_fqs: 1
/* If the compile-time values are accurate, just leave. */
// rcu_fanout_leaf: 16, CONFIG_RCU_FANOUT_LEAF: 16, nr_cpu_ids: 4, NR_CPUS: 4
if (rcu_fanout_leaf == CONFIG_RCU_FANOUT_LEAF &&
nr_cpu_ids == NR_CPUS)
return;
// return 수행
/*
* Compute number of nodes that can be handled an rcu_node tree
* with the given number of levels. Setting rcu_capacity[0] makes
* some of the arithmetic easier.
*/
rcu_capacity[0] = 1;
rcu_capacity[1] = rcu_fanout_leaf;
for (i = 2; i <= MAX_RCU_LVLS; i++)
rcu_capacity[i] = rcu_capacity[i - 1] * CONFIG_RCU_FANOUT;
/*
* The boot-time rcu_fanout_leaf parameter is only permitted
* to increase the leaf-level fanout, not decrease it. Of course,
* the leaf-level fanout cannot exceed the number of bits in
* the rcu_node masks. Finally, the tree must be able to accommodate
* the configured number of CPUs. Complain and fall back to the
* compile-time values if these limits are exceeded.
*/
if (rcu_fanout_leaf < CONFIG_RCU_FANOUT_LEAF ||
rcu_fanout_leaf > sizeof(unsigned long) * 8 ||
n > rcu_capacity[MAX_RCU_LVLS]) {
WARN_ON(1);
return;
}
/* Calculate the number of rcu_nodes at each level of the tree. */
for (i = 1; i <= MAX_RCU_LVLS; i++)
if (n <= rcu_capacity[i]) {
for (j = 0; j <= i; j++)
num_rcu_lvl[j] =
DIV_ROUND_UP(n, rcu_capacity[i - j]);
rcu_num_lvls = i;
for (j = i + 1; j <= MAX_RCU_LVLS; j++)
num_rcu_lvl[j] = 0;
break;
}
/* Calculate the total number of rcu_node structures. */
rcu_num_nodes = 0;
for (i = 0; i <= MAX_RCU_LVLS; i++)
rcu_num_nodes += num_rcu_lvl[i];
rcu_num_nodes -= n;
}
- rcu_init_one(&rcu_bh_state)한일:
- // (&rcu_bh_state)->levelcnt[0]: 1
- // (&rcu_bh_state)->levelspread[0]: 4
- // &((&rcu_bh_state)->level[0])->lock 사용한 spinlock 초기화
- // &((&rcu_bh_state)->level[0])->fqslock 사용한 spinlock 초기화
- // ((&rcu_bh_state)->level[0])->completed: 0xfffffed4
- // ((&rcu_bh_state)->level[0])->qsmask: 0
- // ((&rcu_bh_state)->level[0])->qsmaskinit: 0
- // ((&rcu_bh_state)->level[0])->grplo: 0
- // ((&rcu_bh_state)->level[0])->grphi: 3
- // ((&rcu_bh_state)->level[0])->gpnum: 0
- // ((&rcu_bh_state)->level[0])->grpmask: 0
- // ((&rcu_bh_state)->level[0])->parent: NULL
- // ((&rcu_bh_state)->level[0])->level: 0
- // &((&rcu_bh_state)->level[0])->blkd_tasks 을 사용한 list 초기화
- //
- // (&rcu_bh_state)->rda: &rcu_bh_data
- // &(&(&rcu_bh_state)->gp_wq)->lock을 사용한 spinlock 초기화
- // &(&(&rcu_bh_state)->gp_wq)->task_list를 사용한 list 초기화
- // (&(&rcu_bh_state)->wakeup_work)->flags: 0
- // (&(&rcu_bh_state)->wakeup_work)->func: rsp_wakeup
- //
- // (&rcu_bh_state)->level[0]
- //
- // pcp0->mynode: (&rcu_bh_state)->level[0]
- // pcp1->mynode: (&rcu_bh_state)->level[0]
- // pcp2->mynode: (&rcu_bh_state)->level[0]
- // pcp3->mynode: (&rcu_bh_state)->level[0]
- //
- // pcp0->grpmask: 1
- // pcp0->nxtlist: NULL
- // pcp0->nxttail[0...3]: [pcp0] &(&rcu_bh_data)->nxtlist
- // pcp0->qlen_lazy: 0
- // pcp0->qlen: 0
- // pcp0->dynticks: [pcp0] &rcu_dynticks
- // pcp0->cpu: 0
- // pcp0->rsp: &rcu_bh_state
- // pcp1->grpmask: 2
- // pcp1->nxtlist: NULL
- // pcp1->nxttail[0...3]: [pcp0] &(&rcu_bh_data)->nxtlist
- // pcp1->qlen_lazy: 0
- // pcp1->qlen: 0
- // pcp1->dynticks: [pcp1] &rcu_dynticks
- // pcp1->cpu: 1
- // pcp1->rsp: &rcu_bh_state
- // pcp2->grpmask: 4
- // pcp2->nxtlist: NULL
- // pcp2->nxttail[0...3]: [pcp2] &(&rcu_bh_data)->nxtlist
- // pcp2->qlen_lazy: 0
- // pcp2->qlen: 0
- // pcp2->dynticks: [pcp2] &rcu_dynticks
- // pcp2->cpu: 2
- // pcp2->rsp: &rcu_bh_state
- // pcp3->grpmask: 8
- // pcp3->nxtlist: NULL
- // pcp3->nxttail[0...3]: [pcp3] &(&rcu_bh_data)->nxtlist
- // pcp3->qlen_lazy: 0
- // pcp3->qlen: 0
- // pcp3->dynticks: [pcp3] &rcu_dynticks
- // pcp3->cpu: 3
- // pcp3->rsp: &rcu_bh_state
- //
- // rcu_struct_flavors에 (&rcu_bh_state)->flavors를 list 추가
// ARM10C 20140927
// &rcu_bh_state, &rcu_bh_data
static void __init rcu_init_one(struct rcu_state *rsp,
struct rcu_data __percpu *rda)
{
static char *buf[] = { "rcu_node_0",
"rcu_node_1",
"rcu_node_2",
"rcu_node_3" }; /* Match MAX_RCU_LVLS */
static char *fqs[] = { "rcu_node_fqs_0",
"rcu_node_fqs_1",
"rcu_node_fqs_2",
"rcu_node_fqs_3" }; /* Match MAX_RCU_LVLS */
int cpustride = 1;
// cpustride: 1
int i;
int j;
struct rcu_node *rnp;
// MAX_RCU_LVLS: 4, ARRAY_SIZE(buf): 4
BUILD_BUG_ON(MAX_RCU_LVLS > ARRAY_SIZE(buf)); /* Fix buf[] init! */
/* Silence gcc 4.8 warning about array index out of range. */
// rcu_num_lvls: 1, RCU_NUM_LVLS: 1
if (rcu_num_lvls > RCU_NUM_LVLS)
panic("rcu_init_one: rcu_num_lvls overflow");
/* Initialize the level-tracking arrays. */
// rcu_num_lvls: 1
for (i = 0; i < rcu_num_lvls; i++)
// i:0, rsp->levelcnt[0]: (&rcu_bh_state)->levelcnt[0], num_rcu_lvl[0]: 1
rsp->levelcnt[i] = num_rcu_lvl[i];
// rsp->levelcnt[0]: (&rcu_bh_state)->levelcnt[0]: 1
// rcu_num_lvls: 1
for (i = 1; i < rcu_num_lvls; i++)
rsp->level[i] = rsp->level[i - 1] + rsp->levelcnt[i - 1];
// rsp: &rcu_bh_state
rcu_init_levelspread(rsp);
// rcu_init_levelspread에서 한일:
// rsp->levelspread[0]: (&rcu_bh_state)->levelspread[0]: 4
/* Initialize the elements themselves, starting from the leaves. */
// rcu_num_lvls: 1
for (i = rcu_num_lvls - 1; i >= 0; i--) {
// i: 0, cpustride: 1, rsp->levelspread[0]: (&rcu_bh_state)->levelspread[0]: 4
cpustride *= rsp->levelspread[i];
// cpustride: 4
// i: 0, rsp->level[0]: (&rcu_bh_state)->level[0]
rnp = rsp->level[i];
// rnp: (&rcu_bh_state)->level[0]: &rcu_bh_state.node[0]
// i: 0, rsp->levelcnt[0]: (&rcu_bh_state)->levelcnt[0]: 1
for (j = 0; j < rsp->levelcnt[i]; j++, rnp++) {
// &rnp->lock: &((&rcu_bh_state)->level[0])->lock
raw_spin_lock_init(&rnp->lock);
// &((&rcu_bh_state)->level[0])->lock 사용한 spinlock 초기화
// &rnp->lock: &((&rcu_bh_state)->level[0])->lock,
// i: 0, rcu_node_class[0], buf[0]: "rcu_node_0"
lockdep_set_class_and_name(&rnp->lock,
&rcu_node_class[i], buf[i]); // null function
// &rnp->fqslock: &((&rcu_bh_state)->level[0])->fqslock
raw_spin_lock_init(&rnp->fqslock);
// &((&rcu_bh_state)->level[0])->fqslock 사용한 spinlock 초기화
// &rnp->fqslock: &((&rcu_bh_state)->level[0])->fqslock,
// i: 0, rcu_fqs_class[0], fqs[0]: "rcu_node_fqs_0"
lockdep_set_class_and_name(&rnp->fqslock,
&rcu_fqs_class[i], fqs[i]); // null function
// rnp: ((&rcu_bh_state)->level[0])->gpnum,
// rsp->gpnum: (&rcu_bh_state)->gpnum: 0xfffffed4
rnp->gpnum = rsp->gpnum;
// rnp->gpnum: ((&rcu_bh_state)->level[0])->gpnum: 0xfffffed4
// rnp->completed: ((&rcu_bh_state)->level[0])->completed,
// rsp->completed: (&rcu_bh_state)->completed: 0xfffffed4
rnp->completed = rsp->completed;
// rnp->completed: ((&rcu_bh_state)->level[0])->completed: 0xfffffed4
// rnp->qsmask: ((&rcu_bh_state)->level[0])->qsmask
rnp->qsmask = 0;
// rnp->qsmask: ((&rcu_bh_state)->level[0])->qsmask: 0
// rnp->qsmaskinit: ((&rcu_bh_state)->level[0])->qsmaskinit
rnp->qsmaskinit = 0;
// rnp->qsmaskinit: ((&rcu_bh_state)->level[0])->qsmaskinit: 0
// rnp->grplo: ((&rcu_bh_state)->level[0])->grplo, j: 0, cpustride: 4
rnp->grplo = j * cpustride;
// rnp->grplo: ((&rcu_bh_state)->level[0])->grplo: 0
// rnp->grphi: ((&rcu_bh_state)->level[0])->grphi, j: 0, cpustride: 4
rnp->grphi = (j + 1) * cpustride - 1;
// rnp->grphi: ((&rcu_bh_state)->level[0])->grphi: 3
// rnp->grphi: ((&rcu_bh_state)->level[0])->grphi: 3, NR_CPUS: 4
if (rnp->grphi >= NR_CPUS)
rnp->grphi = NR_CPUS - 1;
// i: 0
if (i == 0) {
// rnp->gpnum: ((&rcu_bh_state)->level[0])->gpnum: 0xfffffed4
rnp->grpnum = 0;
// rnp->gpnum: ((&rcu_bh_state)->level[0])->gpnum: 0
// rnp->grpmask: ((&rcu_bh_state)->level[0])->grpmask
rnp->grpmask = 0;
// rnp->grpmask: ((&rcu_bh_state)->level[0])->grpmask: 0
// rnp->parent: ((&rcu_bh_state)->level[0])->parent
rnp->parent = NULL;
// rnp->parent: ((&rcu_bh_state)->level[0])->parent: NULL
} else {
rnp->grpnum = j % rsp->levelspread[i - 1];
rnp->grpmask = 1UL << rnp->grpnum;
rnp->parent = rsp->level[i - 1] +
j / rsp->levelspread[i - 1];
}
// rnp->level: ((&rcu_bh_state)->level[0])->level, i: 0
rnp->level = i;
// rnp->level: ((&rcu_bh_state)->level[0])->level: 0
// &rnp->blkd_tasks: &((&rcu_bh_state)->level[0])->blkd_tasks
INIT_LIST_HEAD(&rnp->blkd_tasks);
// &rnp->blkd_tasks: &((&rcu_bh_state)->level[0])->blkd_tasks 을 사용한 list 초기화
// rnp: (&rcu_bh_state)->level[0]
rcu_init_one_nocb(rnp); // null function
}
}
// rsp->rda: (&rcu_bh_state)->rda, rda: &rcu_bh_data
rsp->rda = rda;
// rsp->rda: (&rcu_bh_state)->rda: &rcu_bh_data
// &rsp->gp_wq: &(&rcu_bh_state)->gp_wq
init_waitqueue_head(&rsp->gp_wq);
// init_waitqueue_head에서 한일:
// &q->lock: &(&(&rcu_bh_state)->gp_wq)->lock을 사용한 spinlock 초기화
// &q->task_list: &(&(&rcu_bh_state)->gp_wq)->task_list를 사용한 list 초기화
// &rsp->wakeup_work: &(&rcu_bh_state)->wakeup_work
init_irq_work(&rsp->wakeup_work, rsp_wakeup);
// init_irq_work에서 한일:
// work->flags: (&(&rcu_bh_state)->wakeup_work)->flags: 0
// work->func: (&(&rcu_bh_state)->wakeup_work)->func: rsp_wakeup
// rcu_num_lvls: 1, rsp->level[0]: (&rcu_bh_state)->level[0]
rnp = rsp->level[rcu_num_lvls - 1];
// rnp: (&rcu_bh_state)->level[0]
for_each_possible_cpu(i) {
// for ((i) = -1; (i) = cpumask_next((i), (cpu_possible_mask)), (i) < nr_cpu_ids; )
// i: 0, rnp->grphi: ((&rcu_bh_state)->level[0])->grphi: 3
while (i > rnp->grphi)
rnp++;
// rsp->rda: (&rcu_bh_state)->rda: &rcu_bh_data, i: 0
// per_cpu_ptr(&rcu_bh_data, 0)->mynode: [pcp0] (&rcu_bh_data)->mynode,
// rnp: (&rcu_bh_state)->level[0]
per_cpu_ptr(rsp->rda, i)->mynode = rnp;
// per_cpu_ptr(&rcu_bh_data, 0)->mynode: [pcp0] (&rcu_bh_data)->mynode: (&rcu_bh_state)->level[0]
// i: 0, rsp: &rcu_bh_state
rcu_boot_init_percpu_data(i, rsp);
// rcu_boot_init_percpu_data(0) 에서 한일:
// rdp->grpmask: [pcp0] (&rcu_bh_data)->grpmask: 1
// rdp->nxtlist: [pcp0] (&rcu_bh_data)->nxtlist: NULL
// rdp->nxttail[0...3]: [pcp0] (&rcu_bh_data)->nxttail[0...3]: [pcp0] &(&rcu_bh_data)->nxtlist
// rdp->qlen_lazy: [pcp0] (&rcu_bh_data)->qlen_lazy: 0
// rdp->qlen: [pcp0] (&rcu_bh_data)->qlen: 0
// rdp->dynticks: [pcp0] (&rcu_bh_data)->dynticks: [pcp0] &rcu_dynticks
// rdp->cpu: [pcp0] (&rcu_bh_data)->cpu: 0
// rdp->rsp: [pcp0] (&rcu_bh_data)->rsp: &rcu_bh_state
//
// rcu_boot_init_percpu_data(1) 에서 한일:
// rdp->grpmask: [pcp1] (&rcu_bh_data)->grpmask: 2
// rdp->nxtlist: [pcp1] (&rcu_bh_data)->nxtlist: NULL
// rdp->nxttail[0...3]: [pcp1] (&rcu_bh_data)->nxttail[0...3]: [pcp0] &(&rcu_bh_data)->nxtlist
// rdp->qlen_lazy: [pcp1] (&rcu_bh_data)->qlen_lazy: 0
// rdp->qlen: [pcp1] (&rcu_bh_data)->qlen: 0
// rdp->dynticks: [pcp1] (&rcu_bh_data)->dynticks: [pcp1] &rcu_dynticks
// rdp->cpu: [pcp1] (&rcu_bh_data)->cpu: 1
// rdp->rsp: [pcp1] (&rcu_bh_data)->rsp: &rcu_bh_state
//
// rcu_boot_init_percpu_data(2) 에서 한일:
// rdp->grpmask: [pcp2] (&rcu_bh_data)->grpmask: 4
// rdp->nxtlist: [pcp2] (&rcu_bh_data)->nxtlist: NULL
// rdp->nxttail[0...3]: [pcp2] (&rcu_bh_data)->nxttail[0...3]: [pcp2] &(&rcu_bh_data)->nxtlist
// rdp->qlen_lazy: [pcp2] (&rcu_bh_data)->qlen_lazy: 0
// rdp->qlen: [pcp2] (&rcu_bh_data)->qlen: 0
// rdp->dynticks: [pcp2] (&rcu_bh_data)->dynticks: [pcp2] &rcu_dynticks
// rdp->cpu: [pcp2] (&rcu_bh_data)->cpu: 2
// rdp->rsp: [pcp2] (&rcu_bh_data)->rsp: &rcu_bh_state
//
// rcu_boot_init_percpu_data(3) 에서 한일:
// rdp->grpmask: [pcp3] (&rcu_bh_data)->grpmask: 8
// rdp->nxtlist: [pcp3] (&rcu_bh_data)->nxtlist: NULL
// rdp->nxttail[0...3]: [pcp3] (&rcu_bh_data)->nxttail[0...3]: [pcp3] &(&rcu_bh_data)->nxtlist
// rdp->qlen_lazy: [pcp3] (&rcu_bh_data)->qlen_lazy: 0
// rdp->qlen: [pcp3] (&rcu_bh_data)->qlen: 0
// rdp->dynticks: [pcp3] (&rcu_bh_data)->dynticks: [pcp3] &rcu_dynticks
// rdp->cpu: [pcp3] (&rcu_bh_data)->cpu: 3
// rdp->rsp: [pcp3] (&rcu_bh_data)->rsp: &rcu_bh_state
}
// rsp->flavors: (&rcu_bh_state)->flavors
list_add(&rsp->flavors, &rcu_struct_flavors);
// rcu_struct_flavors에 (&rcu_bh_state)->flavors를 list 추가
}
tree_plugin.h::__rcu_init_preempt()
static void __init __rcu_init_preempt(void)
{
rcu_init_one(&rcu_preempt_state, &rcu_preempt_data);
// rcu_init_one(&rcu_preempt_state)한일:
// (&rcu_preempt_state)->levelcnt[0]: 1
// (&rcu_preempt_state)->levelspread[0]: 4
// &((&rcu_preempt_state)->level[0])->lock 사용한 spinlock 초기화
// &((&rcu_preempt_state)->level[0])->fqslock 사용한 spinlock 초기화
// ((&rcu_preempt_state)->level[0])->completed: 0xfffffed4
// ((&rcu_preempt_state)->level[0])->qsmask: 0
// ((&rcu_preempt_state)->level[0])->qsmaskinit: 0
// ((&rcu_preempt_state)->level[0])->grplo: 0
// ((&rcu_preempt_state)->level[0])->grphi: 3
// ((&rcu_preempt_state)->level[0])->gpnum: 0
// ((&rcu_preempt_state)->level[0])->grpmask: 0
// ((&rcu_preempt_state)->level[0])->parent: NULL
// ((&rcu_preempt_state)->level[0])->level: 0
// &((&rcu_preempt_state)->level[0])->blkd_tasks 을 사용한 list 초기화
//
// (&rcu_preempt_state)->rda: &rcu_preempt_data
// &(&(&rcu_preempt_state)->gp_wq)->lock을 사용한 spinlock 초기화
// &(&(&rcu_preempt_state)->gp_wq)->task_list를 사용한 list 초기화
// (&(&rcu_preempt_state)->wakeup_work)->flags: 0
// (&(&rcu_preempt_state)->wakeup_work)->func: rsp_wakeup
//
// (&rcu_preempt_state)->level[0]
//
// [pcp0] (&rcu_preempt_data)->mynode: (&rcu_preempt_state)->level[0]
// [pcp1] (&rcu_preempt_data)->mynode: (&rcu_preempt_state)->level[0]
// [pcp2] (&rcu_preempt_data)->mynode: (&rcu_preempt_state)->level[0]
// [pcp3] (&rcu_preempt_data)->mynode: (&rcu_preempt_state)->level[0]
//
// [pcp0] (&rcu_preempt_data)->grpmask: 1
// [pcp0] (&rcu_preempt_data)->nxtlist: NULL
// [pcp0] (&rcu_preempt_data)->nxttail[0...3]: [pcp0] &(&rcu_preempt_data)->nxtlist
// [pcp0] (&rcu_preempt_data)->qlen_lazy: 0
// [pcp0] (&rcu_preempt_data)->qlen: 0
// [pcp0] (&rcu_preempt_data)->dynticks: [pcp0] &rcu_dynticks
// [pcp0] (&rcu_preempt_data)->cpu: 0
// [pcp0] (&rcu_preempt_data)->rsp: &rcu_preempt_state
// [pcp1] (&rcu_preempt_data)->grpmask: 2
// [pcp1] (&rcu_preempt_data)->nxtlist: NULL
// [pcp1] (&rcu_preempt_data)->nxttail[0...3]: [pcp0] &(&rcu_preempt_data)->nxtlist
// [pcp1] (&rcu_preempt_data)->qlen_lazy: 0
// [pcp1] (&rcu_preempt_data)->qlen: 0
// [pcp1] (&rcu_preempt_data)->dynticks: [pcp1] &rcu_dynticks
// [pcp1] (&rcu_preempt_data)->cpu: 1
// [pcp1] (&rcu_preempt_data)->rsp: &rcu_preempt_state
// [pcp2] (&rcu_preempt_data)->grpmask: 4
// [pcp2] (&rcu_preempt_data)->nxtlist: NULL
// [pcp2] (&rcu_preempt_data)->nxttail[0...3]: [pcp2] &(&rcu_preempt_data)->nxtlist
// [pcp2] (&rcu_preempt_data)->qlen_lazy: 0
// [pcp2] (&rcu_preempt_data)->qlen: 0
// [pcp2] (&rcu_preempt_data)->dynticks: [pcp2] &rcu_dynticks
// [pcp2] (&rcu_preempt_data)->cpu: 2
// [pcp2] (&rcu_preempt_data)->rsp: &rcu_preempt_state
// [pcp3] (&rcu_preempt_data)->grpmask: 8
// [pcp3] (&rcu_preempt_data)->nxtlist: NULL
// [pcp3] (&rcu_preempt_data)->nxttail[0...3]: [pcp3] &(&rcu_preempt_data)->nxtlist
// [pcp3] (&rcu_preempt_data)->qlen_lazy: 0
// [pcp3] (&rcu_preempt_data)->qlen: 0
// [pcp3] (&rcu_preempt_data)->dynticks: [pcp3] &rcu_dynticks
// [pcp3] (&rcu_preempt_data)->cpu: 3
// [pcp3] (&rcu_preempt_data)->rsp: &rcu_preempt_state
//
// rcu_struct_flavors에 (&rcu_preempt_state)->flavors를 list 추가
}
tree.c:: RCU_STATE_INITIALIZER(sname, sabbr, cr)
#define RCU_STATE_INITIALIZER(sname, sabbr, cr) \
static char sname##_varname[] = #sname; \
static const char *tp_##sname##_varname __used __tracepoint_string = sname##_varname; \
struct rcu_state sname##_state = { \
.level = { &sname##_state.node[0] }, \
.call = cr, \
.fqs_state = RCU_GP_IDLE, \
.gpnum = 0UL - 300UL, \
.completed = 0UL - 300UL, \
.orphan_lock = __RAW_SPIN_LOCK_UNLOCKED(&sname##_state.orphan_lock), \
.orphan_nxttail = &sname##_state.orphan_nxtlist, \
.orphan_donetail = &sname##_state.orphan_donelist, \
.barrier_mutex = __MUTEX_INITIALIZER(sname##_state.barrier_mutex), \
.onoff_mutex = __MUTEX_INITIALIZER(sname##_state.onoff_mutex), \
.name = sname##_varname, \
.abbr = sabbr, \
}; \
DEFINE_PER_CPU(struct rcu_data, sname##_data)
RCU_STATE_INITIALIZER(rcu_sched, 's', call_rcu_sched);
RCU_STATE_INITIALIZER(rcu_bh, 'b', call_rcu_bh);
softirq.c::open_softirq()
// ARM10C 20140927
// RCU_SOFTIRQ: 9, rcu_process_callbacks
void open_softirq(int nr, void (*action)(struct softirq_action *))
{
// nr: 7, action: run_rebalance_domains
// nr: 9, action: rcu_process_callbacks
softirq_vec[nr].action = action;
// softirq_vec[7].action: run_rebalance_domains
// softirq_vec[9].action: rcu_process_callbacks
}
cpu.h::cpu_notifier()
// ARM10C 20140927
// cpu_notifier(rcu_cpu_notify, 0):
// {
// static struct notifier_block rcu_cpu_notify_nb =
// { .notifier_call = rcu_cpu_notify, .priority = 0 };
// register_cpu_notifier(&rcu_cpu_notify_nb);
// }
#define cpu_notifier(fn, pri) { \
static struct notifier_block fn##_nb = \
{ .notifier_call = fn, .priority = pri }; \
register_cpu_notifier(&fn##_nb); \
}
suspend.h::pm_notifier()
// ARM10C 20140927
// #define pm_notifier(rcu_pm_notify, 0):
// {
// static struct notifier_block rcu_pm_notify_nb =
// { .notifier_call = rcu_pm_notify, .priority = 0 };
// register_pm_notifier(&rcu_pm_notify_nb);
// }
#define pm_notifier(fn, pri) { \
static struct notifier_block fn##_nb = \
{ .notifier_call = fn, .priority = pri }; \
register_pm_notifier(&fn##_nb); \
}
wait.c::init_waitqueue_head()
#define init_waitqueue_head(q) \
do { \
static struct lock_class_key __key; \
\
__init_waitqueue_head((q), #q, &__key); \
} while (0)
irq_work.h::init_irq_work()
static inline
void init_irq_work(struct irq_work *work, void (*func)(struct irq_work *))
{
work->flags = 0;
work->func = func;
}
tree.c::rcu_boot_init_percpu_data()
static void __init
rcu_boot_init_percpu_data(int cpu, struct rcu_state *rsp)
{
unsigned long flags;
struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
struct rcu_node *rnp = rcu_get_root(rsp);
// rn
/* Set up local state, ensuring consistent view of global state. */
raw_spin_lock_irqsave(&rnp->lock, flags);
rdp->grpmask = 1UL << (cpu - rdp->mynode->grplo);
// rdp->grpmask: [pcp0] &rcu_bh_data->grpmask
// rdp: [pcp0] &rcu_bh_data
init_callback_list(rdp);
// rdp->qlen_lazy: [pcp0] (&rcu_bh_data)->qlen_lazy
rdp->qlen_lazy = 0;
// rdp->qlen_lazy: [pcp0] (&rcu_bh_data)->qlen_lazy:0
ACCESS_ONCE(rdp->qlen) = 0;
// cpu:0 [pcp0] &per_cpu((&rcu_bh_data)->dynticks, 0 )
rdp->dynticks = &per_cpu(rcu_dynticks, cpu);
WARN_ON_ONCE(rdp->dynticks->dynticks_nesting != DYNTICK_TASK_EXIT_IDLE);
WARN_ON_ONCE(atomic_read(&rdp->dynticks->dynticks) != 1);
rdp->cpu = cpu;
// [pcp0] (&rcu_bh_data)->cpu: cpu: 0
rdp->rsp = rsp;
// [pcp0] (&rcu_bh_data)->rsp: rsp: &rcu_bh_state
rcu_boot_init_nocb_percpu_data(rdp);
// null function
raw_spin_unlock_irqrestore(&rnp->lock, flags);
}
notifier.c::blocking_notifier_chain_register()
int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
struct notifier_block *n)
{
int ret;
/*
* This code gets used during boot-up, when task switching is
* not yet working and interrupts must remain disabled. At
* such times we must not call down_write().
*/
if (unlikely(system_state == SYSTEM_BOOTING))
return notifier_chain_register(&nh->head, n);
down_write(&nh->rwsem);
ret = notifier_chain_register(&nh->head, n);
up_write(&nh->rwsem);
return ret;
}
EXPORT_SYMBOL_GPL(blocking_notifier_chain_register);
cpumask.h::for_each_online_cpu()
- for_each_online_cpu(cpu) rcu_cpu_notify(NULL, CPU_UP_PREPARE, (void *)(long)cpu);
#define for_each_online_cpu(cpu) for_each_cpu((cpu), cpu_online_mask)
// #define for_each_cpu(i, cpu_online_mask)
// for ((i) = -1; (i) = cpumask_next((i), (cpu_online_mask)), (i) < nr_cpu_ids; )
tree.c::rcu_cpu_notify()
static int rcu_cpu_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
// hcpu: 0
long cpu = (long)hcpu;
// cpu: 0
// rcu_state->rda: (&rcu_preempt_state)->rda: &rcu_preempt_data, cpu: 0
// per_cpu_ptr(&rcu_preempt_data, 0): [pcp0] &rcu_preempt_data
struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, cpu);
// rdp: [pcp0] &rcu_preempt_data
// rdp->mynode: [pcp0] (&rcu_preempt_data)->mynode: (&rcu_preempt_state)->level[0]: &rcu_preempt_state.node[0]
struct rcu_node *rnp = rdp->mynode;
// rnp: (&rcu_preempt_state)->level[0]
struct rcu_state *rsp;
trace_rcu_utilization(TPS("Start CPU hotplug"));
// action: CPU_UP_PREPARE: 0x0003
switch (action) {
case CPU_UP_PREPARE:
case CPU_UP_PREPARE_FROZEN:
// cpu: 0
rcu_prepare_cpu(cpu);
// cpu: 0
rcu_prepare_kthreads(cpu); // null function
break;
case CPU_ONLINE:
case CPU_DOWN_FAILED:
rcu_boost_kthread_setaffinity(rnp, -1);
break;
case CPU_DOWN_PREPARE:
rcu_boost_kthread_setaffinity(rnp, cpu);
break;
case CPU_DYING:
case CPU_DYING_FROZEN:
for_each_rcu_flavor(rsp)
rcu_cleanup_dying_cpu(rsp);
break;
case CPU_DEAD:
case CPU_DEAD_FROZEN:
case CPU_UP_CANCELED:
case CPU_UP_CANCELED_FROZEN:
for_each_rcu_flavor(rsp)
rcu_cleanup_dead_cpu(cpu, rsp);
break;
default:
break;
}
trace_rcu_utilization(TPS("End CPU hotplug"));
return NOTIFY_OK;
}
tree.c::rcu_prepare_cpu()
- rcu_prepare_cpu에서 한일: // pcp0->beenonline: 1 // pcp0->preemptible: 0 // pcp0->len_last_fqs_check: 0 // pcp0->n_force_qs_snap: 0 // pcp0->blimit: 10 // pcp0->nxtlist: NULL // pcp0->nxttail[0...3]: [pcp0] &(&rcu_bh_data)->nxtlist // pcp0->dynticks->dynticks_nesting: 0x140000000000000 // pcp0->dynticks->dynticks: 1 // pcp0->qsmaskinit: 1 // pcp0->gpnum: 0xfffffed4 // pcp0->passed_quiesce: 0 // pcp0->qs_pending: 0 // // pcp0->beenonline: 1 // pcp0->preemptible: 0 // pcp0->len_last_fqs_check: 0 // pcp0->n_force_qs_snap: 0 // pcp0->blimit: 10 // pcp0->nxtlist: NULL // pcp0->nxttail[0...3]: [pcp0] &(&rcu_sched_data)->nxtlist // pcp0->dynticks->dynticks_nesting: 0x140000000000000 // pcp0->dynticks->dynticks: 1 // pcp0->qsmaskinit: 1 // pcp0->gpnum: 0xfffffed4 // pcp0->passed_quiesce: 0 // pcp0->qs_pending: 0 // // pcp0->beenonline: 1 // pcp0->preemptible: 1 //pcp0->len_last_fqs_check: 0 // pcp0->n_force_qs_snap: 0 // pcp0->blimit: 10 // pcp0->nxtlist: NULL // pcp0->nxttail[0...3]: [pcp0] &(&rcu_preempt_data)->nxtlist // pcp0->dynticks->dynticks_nesting: 0x140000000000000 //pcp0->dynticks->dynticks: 1 // pcp0->qsmaskinit: 1 // pcp0->gpnum: 0xfffffed4 // pcp0->passed_quiesce: 0 //pcp0->qs_pending: 0
// ARM10C 20140927
// cpu: 0
static void rcu_prepare_cpu(int cpu)
{
struct rcu_state *rsp;
for_each_rcu_flavor(rsp)
// for (rsp = list_first_entry(&rcu_struct_flavors, typeof(*rsp), flavors);
// &rsp->flavors != (&rcu_struct_flavors); rsp = list_next_entry(rsp, flavors))
// cpu: 0, rsp: &rcu_bh_state, rsp->name: (&rcu_bh_state)->name: "rcu_bh", strcmp("rcu_bh", "rcu_preempt"): -1
// cpu: 0, rsp: &rcu_sched_data, rsp->name: (&rcu_bh_state)->name: "rcu_sched", strcmp("rcu_sched", "rcu_preempt"): -1
// cpu: 0, rsp: &rcu_preempt_data, rsp->name: (&rcu_preempt_state)->name: "rcu_preempt", strcmp("rcu_preempt", "rcu_preempt"): 0
rcu_init_percpu_data(cpu, rsp,
strcmp(rsp->name, "rcu_preempt") == 0);
}
tree.c::rcu_init_percpu_data()
// ARM10C 20140927
// cpu: 0, rsp: &rcu_bh_state, 0
static void
rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible)
{
unsigned long flags;
unsigned long mask;
// rsp->rda: (&rcu_bh_state)->rda: &rcu_bh_data, cpu: 0
// per_cpu_ptr(&rcu_bh_data, 0): [pcp0] &rcu_bh_data
struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
// rdp: [pcp0] &rcu_bh_data
// rsp: &rcu_bh_state, rcu_get_root(&rcu_bh_state): &(&rcu_bh_state)->node[0]
struct rcu_node *rnp = rcu_get_root(rsp);
// rnp: &(&rcu_bh_state)->node[0]
/* Exclude new grace periods. */
// &rsp->onoff_mutex: &(&rcu_bh_state)->onoff_mutex
mutex_lock(&rsp->onoff_mutex);
// &rsp->onoff_mutex: &(&rcu_bh_state)->onoff_mutex을 사용한 mutex lock 수행
/* Set up local state, ensuring consistent view of global state. */
// &rnp->lock: &(&(&rcu_bh_state)->node[0])->lock
raw_spin_lock_irqsave(&rnp->lock, flags);
// &rnp->lock: &(&(&rcu_bh_state)->node[0])->lock을 사용한 spinlock을 걸고 cpsr을 flags에 저장
// rdp->beenonline: [pcp0] (&rcu_bh_data)->beenonline
rdp->beenonline = 1; /* We have now been online. */
// rdp->beenonline: [pcp0] (&rcu_bh_data)->beenonline: 1
// rdp->preemptible: [pcp0] (&rcu_bh_data)->preemptible, preemptible: 0
rdp->preemptible = preemptible;
// rdp->preemptible: [pcp0] (&rcu_bh_data)->preemptible: 0
// rdp->len_last_fqs_check: [pcp0] (&rcu_bh_data)->len_last_fqs_check
rdp->qlen_last_fqs_check = 0;
// rdp->len_last_fqs_check: [pcp0] (&rcu_bh_data)->len_last_fqs_check: 0
// rdp->n_force_qs_snap: [pcp0] (&rcu_bh_data)->n_force_qs_snap
// rsp->n_force_qs: (&rcu_bh_state)->n_force_qs: 0
rdp->n_force_qs_snap = rsp->n_force_qs;
// rdp->n_force_qs_snap: [pcp0] (&rcu_bh_data)->n_force_qs_snap: 0
// rdp->blimit: [pcp0] (&rcu_bh_data)->blimit, blimit: 10
rdp->blimit = blimit;
// rdp->blimit: [pcp0] (&rcu_bh_data)->blimit: 10
// rdp: [pcp0] &rcu_bh_data
init_callback_list(rdp); /* Re-enable callbacks on this CPU. */
// init_callback_list에서 한일:
// [pcp0] (&rcu_bh_data)->nxtlist: NULL
// [pcp0] (&rcu_bh_data)->nxttail[0...3]: [pcp0] &(&rcu_bh_data)->nxtlist
// rdp->dynticks->dynticks_nesting: [pcp0] (&rcu_bh_data)->dynticks->dynticks_nesting,
// DYNTICK_TASK_EXIT_IDLE: 0x140000000000000
rdp->dynticks->dynticks_nesting = DYNTICK_TASK_EXIT_IDLE;
// rdp->dynticks->dynticks_nesting: [pcp0] (&rcu_bh_data)->dynticks->dynticks_nesting: 0x140000000000000
// rdp->dynticks: [pcp0] (&rcu_bh_data)->dynticks
rcu_sysidle_init_percpu_data(rdp->dynticks); // null function
// &rdp->dynticks->dynticks: [pcp0] (&rcu_bh_data)->dynticks->dynticks: 1,
// atomic_read((&rcu_bh_data)->dynticks->dynticks): 1
atomic_set(&rdp->dynticks->dynticks,
(atomic_read(&rdp->dynticks->dynticks) & ~0x1) + 1);
// &rdp->dynticks->dynticks: [pcp0] (&rcu_bh_data)->dynticks->dynticks: 1
// &rnp->lock: &(&(&rcu_bh_state)->node[0])->lock
raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */
// &rnp->lock: &(&(&rcu_bh_state)->node[0])->lock을 사용한 spinlock을 풀고 flags에 저장된 cpsr을 복원
/* Add CPU to rcu_node bitmasks. */
// rdp->mynode: [pcp0] (&rcu_bh_data)->mynode: (&rcu_bh_state)->level[0]
rnp = rdp->mynode;
// rnp: [pcp0] (&rcu_bh_state)->level[0]
// rdp->grpmask: [pcp0] (&rcu_bh_data)->grpmask: 1
mask = rdp->grpmask;
// mask: 1
do {
/* Exclude any attempts to start a new GP on small systems. */
// &rnp->lock: [pcp0] &((&rcu_bh_state)->level[0])->lock
raw_spin_lock(&rnp->lock); /* irqs already disabled. */
// &rnp->lock: [pcp0] &((&rcu_bh_state)->level[0])->lock을 사용한 spinlock 수행
// rnp->qsmaskinit: [pcp0] ((&rcu_bh_state)->level[0])->qsmaskinit: 0, mask: 1
rnp->qsmaskinit |= mask;
// rnp->qsmaskinit: [pcp0] ((&rcu_bh_state)->level[0])->qsmaskinit: 1
// rnp->grpmask: [pcp0] ((&rcu_bh_state)->level[0])->grpmask: 0, mask: 1
mask = rnp->grpmask;
// mask: 0
// rnp: [pcp0] (&rcu_bh_state)->level[0],
// rdp->mynode: [pcp0] (&rcu_bh_data)->mynode: (&rcu_bh_state)->level[0]
if (rnp == rdp->mynode) {
/*
* If there is a grace period in progress, we will
* set up to wait for it next time we run the
* RCU core code.
*/
// rdp->gpnum: [pcp0] (&rcu_bh_data)->gpnum,
// rnp->completed: [pcp0] ((&rcu_bh_state)->level[0])->completed: 0xfffffed4
rdp->gpnum = rnp->completed;
// rdp->gpnum: [pcp0] (&rcu_bh_data)->gpnum: 0xfffffed4
// rdp->completed: [pcp0] (&rcu_bh_data)->completed,
// rnp->completed: [pcp0] ((&rcu_bh_state)->level[0])->completed: 0xfffffed4
rdp->completed = rnp->completed;
// rdp->completed: [pcp0] (&rcu_bh_data)->completed: 0xfffffed4
// rdp->passed_quiesce: [pcp0] (&rcu_bh_data)->passed_quiesce
rdp->passed_quiesce = 0;
// rdp->passed_quiesce: [pcp0] (&rcu_bh_data)->passed_quiesce: 0
// rdp->qs_pending: [pcp0] (&rcu_bh_data)->qs_pending
rdp->qs_pending = 0;
// rdp->qs_pending: [pcp0] (&rcu_bh_data)->qs_pending: 0
// rsp->name: (&rcu_bh_state)->name: "rcu_bh", rdp->gpnum: [pcp0] (&rcu_bh_data)->gpnum: 0xfffffed4
trace_rcu_grace_period(rsp->name, rdp->gpnum, TPS("cpuonl")); // null function
}
// &rnp->lock: [pcp0] &((&rcu_bh_state)->level[0])->lock
raw_spin_unlock(&rnp->lock); /* irqs already disabled. */
// &rnp->lock: [pcp0] &((&rcu_bh_state)->level[0])->lock을 사용한 spin unlock 수행
// rnp->parent: (&(&rcu_bh_state)->node[0])->parent: NULL
rnp = rnp->parent;
// rnp: NULL
// rnp: NULL, rnp->qsmaskinit: (&(&rcu_bh_state)->node[0])->qsmaskinit: 1, mask: 0
} while (rnp != NULL && !(rnp->qsmaskinit & mask));
local_irq_restore(flags);
// flags에 저장된 cpsr을 복원
// &rsp->onoff_mutex: &(&rcu_bh_state)->onoff_mutex
mutex_unlock(&rsp->onoff_mutex);
// &rsp->onoff_mutex: &(&rcu_bh_state)->onoff_mutex을 사용한 mutex unlock 수행
}