[커널 17차] 58주차

2021.10.10 04:46

ㅇㅇㅇ 조회 수:67

pcpu hint
1. 길이가 제일 긴게 여러 개 있으면 그 중 aligment가 가장 큰 것이 contig_hint가 되고 제일 오른쪽에 위치한 것이 scan_hint가 되는 것이 맞아 보임
2. 또한 길이가 제일 긴 것이 하나면 제일 긴 것이 contig_hint가 되고 contig_hint 보다 왼쪽에 있는 것 들 중 가장 긴 것이 scan_hint가 되는 것이 맞아 보임. 가장 긴 것이 여러 개가 있으면 그 중 가장 오른쪽에 있는 것이 scan_hint가 되어야 할 것으로 보임

 

그러나 pcpu_block_update() 함수에서

1) 코드 상으로는 scan_hint를 만들 수 있는 경우에도 과도하게 scan_hint를 0으로 만들고 있음
2) 또한 contig_hint == scan_hint인 경우에 scan_hint가 왼쪽에 있는 것도 허용하는 것으로 보임

 

원래대로 라면 아래와 같이 바꿔야 할 듯함

604 : contig_hint가 제일 오른쪽이 아닐 수 있어서 죽이는 것으로 바꿀 필요 없음 (기존 contig랑 새 contig 사이에 기존 contig랑 길이가 같은 다른 놈이 있을 수 있다)
612 : scan hint를 보고 살릴 수도 있을 것 같은데 그냥 죽이고 있음 (기존 scan이 존재하고 새 contig보다 왼쪽에 있으면 기존 scan을 유지하는게 맞아보임)
623 : if 문 조건을 XNOR로 바꿔야 맞을 것 같음
626 : else if 조건을 (start > block->scan_hint_start &&block->contig_hint_start < start)으로 바꿔야 한다


관련 패치
- https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1943842.html
- https://github.com/torvalds/linux/commit/382b88e961c7a4196e01cef3249297583d02d608

percpu 내용 : http://jake.dothome.co.kr/setup_per_cpu_areas/


pcpu_next_hint()
- pcpu dynamic memory allocation을 위한 scan 위치를 설정
- 1) scan_hint가 존재하고, 2) scan_hint 보다 contig_hint가 더 오른쪽에 있고 (따라서 contig_hint가 더 길고), 3) alloc해야 하는 크기가 scan_hint 보다 크면 scan_hint 왼쪽에 있는 free 영역은 어차피 allocation할 수 있는 영역이 아니므로 scan_hint 다음 영역부터 scan한다
- 만약 위 세 가지 조건이 만족이 안되면 그냥 left_free부터 scan한다


pcpu_next_fit_region()
- 인자로 chunk의 시작 bit offset, 할당 요구하는 메모리 alloc bits, 요구되는 alignment를 인자로 받아서 요구 사항을 만족하는 할당 가능한 chunk의 block의 1st free 지점 또는 scan_hint 다음 영역을 리턴한다
- 리턴된 영역 내를 scan하면 요구되는 메모리 영역을 찾을 수 있다

- bit offset으로부터 search를 시작할 chunk내의 block index i를 구한다
- bit offset으로부터 search를 시작할 block 내의 bit offset block_off를 구한다
- chunk 내 block에 대해 루프를 돌면서 아래를 수행한다

 

1. 이전 블록에서 시작되는 연속된 free 영역의 크기에 현재 블록의 left free 영역의 크기를 더해서 연속된 free 영역의 크기를 업데이트한다
2. 연속된 free 영역의 크기가 allocation 요구보다 크면 현재 free 영역의 시작 지점을 리턴한다
3. 작으면 현재 block이 free block인 경우 현재 free 영역의 크기에 block size를 더하고 다음 블록으로 넘어간다
4. 아니면 현재 block의 contig_hint 영역이 alignment 요구사항까지 고려했을 때 allocation bit보다 큰지 체크한다. 만약 크면 현재 block의 first free 영역 시작 지점 또는 scan_hint 다음 지점 중 하나를 리턴한다. 둘 중 어느 것을 사용할 지는 함수 pcpu_next_hint() 함수에 의해 결정된다.
5. 현재 block의 contig_hint 영역이 allocation을 만족시키지 못하는 경우 현재 block의 right free 영역을 시작 지점으로 해서 현재 free 영역의 크기를 계산한다. 만약 right free 영역만으로 allocation을 만족시키는 경우 현재 free 영역의 시작 지점을 리턴하고 아니면 다음 블록으로 넘어간다

 

- 모든 block을 찾았으나 만족되는 free 영역이 없으면 현재 chunk의 다음 비트를 리턴한다


pcpu_find_block_fit()
- chunk와 allocation bit, alignment를 인자로 받아서 해당 요구사항을 만족하는 chunk 내 block의 1st free 또는 scan_hint 다음 영역을 리턴한다

- alignment를 고려해서 chunk 전체가 allocation 요구 크기를 만족시킬 수 있는지 판단하고 없으면 실패 리턴한다. 여기서 chunk_md->contig_hit가 사용된다
- chunk_md의 hint를 고려해서 chunk의 1st free 또는 scan_hint 다음 영역을 scan 시작 지점으로 잡는다
- 매크로 pcpu_for_each_fit_region()를 이용해서 chunk 내 allocation 조건을 만족하는 영역을 찾아서 bit_off로 가져오고 리턴한다


pcpu_for_each_fit_region() 매크로
- 함수 pcpu_next_fit_region()를 이용해서 alloc_bit 조건을 만족시키는 다음 free 영역을 찾아서 리턴하는 iterator


pcpu_next_md_free_region()
- 인자로 chunk, bit_off, bits를 받아서 다음 bit_off 부터 chunk 내에 있는 다음 free 영역을 찾아서 리턴한다
- 이 때 bit_off는 찾은 free 영역의 시작점이고 bits는 찾은 free 영역의 길이이다

- bit_off로부터 chunk 내의 시작 block index i를 구한다
- bif_off로부터 시작 block의 offset block_off를 구한다
- 시작 block으로부터 chunk내 마지막 block까지 루프를 돌면서 다음을 수행한다

 

1) bits != 0 이면 이전 block에서 이어지는 free 영역이 있다는 뜻. 따라서 이번 block의 left_free를 이전 free 영역의 크기에 더해 준다. 만약 이번 block이 전체가 empty이면 free 영역의 크기에 페이지 전체를 더하고 다음 block으로 넘어가고, 아니면 업데이트 된 free 영역의 크기와 시작점을 리턴한다
2) 이전 block에서 이어지는 free 영역이 없으면 contig_hint가 있는지 보고 있으면 contig_hint를 bits로 contig_hint_start를 bit_off로 해서 리턴해준다.
3) 만약 contig_hint가 다음 block으로 연결되어 있으면 bits를 right_free로, bit_off를 right_free 시작 지점으로 해서 다음 block으로 넘어간다.


pcpu_for_each_md_free_region() 매크로
- 함수 pcpu_next_md_free_region()를 이용해서 chunk의 free 영역을 찾아서 리턴한다


pcpu_chunk_refresh_hint()
- chunk의 meta data hint (scan/contig)를 업데이트한다
- pcpu_block_refresh_hint()와 비슷하나 인자로 full_scan이 하나 더 있어서 true인 경우 무조건 first_free bit부터 시작하고, contig_hint를 0으로 시작한다
- 또한 루프 매크로를 bitmap_for_each_clear_region() 대신 pcpu_for_each_md_free_region() 매크로를 사용한다
- 나머지는 pcpu_block_refresh_hint() 함수와 동일

XE Login