2014년 3월 5일 수요일

[Linux Kernel] 44주차(2014.03.01) 후기

* 44주차
10차 ARM 리눅스 커널 스터디 44주차(2014.03.01) 후기입니다. 

# 일시 : 2014.03.01 (44주차)
# 장소 : 토즈 타워점
# 참여인원 : 4명
# 스터디 진도 : start_kernel()-> setup_per_cpu_areas() -> pcpu_embed_first_chunk();

# 스터디 주요 논의 내용

# if(max_distance > (VMALLOC_END - VMALLOC_START) * ¾) {
}

75%보다(크기를 계산해 보면 180MB) max_distance가 크면 안된다.

# pcpu_embed_first_chunk () -> pcpu_setup_first_chunk(ai, base)


dyn_size : 0x3000 (12kB)
size_sum : ai->static_size + ai->reserved_size + dyn_size
  // ai->static_size + 0x5000 (20kB : 8kB + 12kB)


# PRINTF 에서 *는 무엇을 의미할까?
참조 링크 : http://www.soen.kr/


pintf에서 *는 폭지정을 인수로부터 전달받는다.
보통은 %5이런식으로 %다음에 숫자가 폭을 지정하나,
가변적으로 폭을 지정하고 싶을때는 인자를 2개 사용해서  *와 출력을 사용한다.


## 예시 1: 폭지정의 예이다.  *으로 하면 폭이 3이되고 출력이 5가 출력된다.
printf(“wwww%*dwww”,3,5);
→ www__5www


## 예시 2 (길님):
35         fprintf( stderr, "%s%0*lx\n", "", 1, 0xf );
36         fprintf( stderr, "%s%0*lx\n", ",", 2, 0xf );
37         fprintf( stderr, "%s%0*lx\n", ",", 3, 0xf );
38         fprintf( stderr, "%s%0*lx\n", ",", 4, 0xf );


출력결과
f
,0f
,00f
,000f


#  BUG_ON 에서 체크하는 것들
ai->nr_groups : 1
ai_static_size : 실제 할당된 size
~PAGE_MASK : 0x00000FFF
!base_addr :  128K만큼 물리주소 0x5FFFFFFF 근처에서 할당받는 주소
~PAGE_MASK : 0x00000FFF
ai->unit_size : 0x8000 (32kB로 가정)
ai->unit_size : 0x8000 & ~PAGE_MASK :
ai->unit_size < PCPU_MIN_UNIT_SIZE : 0x3000 (12kB)
ai->dyn_size < PERCPU_DYNAMIC_EARLY_SIZE
pcpu_verify_alloc_info(ai) <0;


# 4kB단위로 할당 받는 메모리들
group_offsets :
group_sizes:
unit_map :
unit_off :


# 각 cpu에 해당하는 unit_map[0~3] 와 할당 받은 unit_off를 설정하는 과정
1283        for (group = 0, unit = 0; group < ai->nr_groups; group++, unit += i) {           
1284                const struct pcpu_group_info *gi = &ai->groups[group];                   
1285                                                                                         
1286                group_offsets[group] = gi->base_offset;                                  
1287                group_sizes[group] = gi->nr_units * ai->unit_size;                       
1288                                                                                         
1289                for (i = 0; i < gi->nr_units; i++) {                                     
1290                        cpu = gi->cpu_map[i];                                            
1291                        if (cpu == NR_CPUS)                                              
1292                                continue;                                                
1293                                                                                         
1294                        PCPU_SETUP_BUG_ON(cpu > nr_cpu_ids);                             
1295                        PCPU_SETUP_BUG_ON(!cpu_possible(cpu));                           
1296                        PCPU_SETUP_BUG_ON(unit_map[cpu] != UINT_MAX);                    
1297                                                                                         
1298                        unit_map[cpu] = unit + i;                                        
1299                        unit_off[cpu] = gi->base_offset + i * ai->unit_size;             
1300                                                                                         
1301                        /* determine low/high unit_cpu */                                
1302                        if (pcpu_low_unit_cpu == NR_CPUS ||                              
1303                            unit_off[cpu] < unit_off[pcpu_low_unit_cpu])                 
1304                                pcpu_low_unit_cpu = cpu;                                 
1305                        if (pcpu_high_unit_cpu == NR_CPUS ||                             
1306                            unit_off[cpu] > unit_off[pcpu_high_unit_cpu])                
1307                                pcpu_high_unit_cpu = cpu;                                
1308                }                                                                        
1309        }


실행 후 :
// unit : 4
unit_off[0] 의 offset  0x0
unit_off[1] 의 offset  0x8000 * 1
unit_off[2] 의 offset  0x8000 * 2

unit_off[3] 의 offset  0x8000 * 3

# 부팅 중 percpu관련 메시지 예시 ( x86, 우분투 12.04)
[    0.000000] setup_percpu: NR_CPUS:256 nr_cpumask_bits:256 nr_cpu_ids:1 nr_nod
e_ids:1
[    0.000000] PERCPU: Embedded 29 pages/cpu @ffff88003fc00000 s86720 r8192 d238
72 u2097152
[    0.000000] pcpu-alloc: s86720 r8192 d23872 u2097152 alloc=1*2097152
[    0.000000] pcpu-alloc: [0] 0
[    0.000000] Built 1 zonelists in Node order, mobility grouping on.  Total pages: 257913


# pcpu_first_chunk 는 어떤 값이 될까?
1527        pcpu_first_chunk = dchunk ?: schunk;
컴파일로 실험해 보니
dchunk가 NULL이 아니라면 pcup_first_chunk = dchunk가 된다. (우리는 이것)
dchunk가 NULL이라면 pcpu_first_chunk = schunk가 된다. 

#         pcpu_chunk_relocate(pcpu_first_chunk, -1);
&pcpu_slot[11] (list)에 pcpu_first_chunk(&dchunk)가 할당됨

# 왜 11 slot에 할당될까?
dchunk->free_size 가 0x3000 (12kB)이기 때문이다. 
정확히는 소스코드에서 계산되고
return max(highbit - PCPU_SLOT_BASE_SHIFT + 2, 1);
우리는 highbit가 14이기 때문에 return max(11,1 ) = 11 이된다.

slot number와 slot size를 정리하면 다음과 같다.

| slot number | slot size |
|-----------+-------------|
| 13 | 32kB | 
| 12 | 16kB |
| 11 | 8kB | 
| 10 | 4kB |
| 09 | 2kB |
| 08 | 1kB |
| 07 | 512B | 
| 06 | 256B |
| 05 | 128B |
| 04 | 64B |
| 03 | 32B |
| 02 | 16B |
| 01 | 8B |
| 0 | 4B |
|-----------+-------------|


# chunk란 ?

청크는 사전적 의미는 덩어리라는 뜻이다. 정보 덩어리를 나누고 나누어진 덩어리에 대한 정보를 찾기 위한 색인을 정의하여 편리하게 찾기 위한 방법이다.

# 왜 perCPU메모리를 할당해서 사용할까?
1. 각 CPU가 사용하는 메모리 자원을 locking을 위해서 이다.
2. 캐쉬 invalid를 향상 시킨다.

# 스터디 log 1차 
  38f9803..e31c467  master     -> origin/master
Updating 38f9803..e31c467
Fast-forward
arch/arm/include/asm/pgtable.h |   4 +-
include/asm-generic/sections.h |   1 +
include/linux/bitops.h         |   7 +++
include/linux/cpumask.h        |   4 ++
include/linux/kern_levels.h    |   4 ++
include/linux/kernel.h         |   3 +
include/linux/log2.h           |  13 ++++-
include/linux/percpu.h         |   1 +
include/uapi/linux/kernel.h    |   2 +
kernel/cpu.c                   |   1 +
lib/bitmap.c                   |  29 ++++++++++
lib/vsprintf.c                 |   2 +
mm/percpu-km.c                 |   6 ++
mm/percpu.c                    | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
14 files changed, 235 insertions(+), 6 deletions(-)

# 스터디 log 2차
   e31c467..e768777  master     -> origin/master
Updating e31c467..e768777
Fast-forward
 drivers/gpu/drm/vmwgfx/svga3d_surfacedefs.h |   1 +
 include/asm-generic/bitops/non-atomic.h     |   4 +
 include/linux/bitmap.h                      |  15 ++
 include/linux/bitops.h                      |   1 +
 include/linux/cpumask.h                     |  13 +-
 include/linux/kernel.h                      |   1 +
 include/linux/list.h                        |  17 ++
 include/linux/poison.h                      |   1 +
 include/linux/types.h                       |   1 +
 mm/percpu.c                                 | 258 ++++++++++++++++++++++++++-----
 10 files changed, 273 insertions(+), 39 deletions(-)

# 44주차 스터디를 정리해서 그림을 그리면 다음이 된다. 
20140301_study_percpu_map.JPG

댓글 없음:

댓글 쓰기