← Documents Documentation/locking/percpu-rw-semaphore.rst GitHub 원문 ↗

Linux 6.18.37 · Locking

Per-CPU rw semaphore

Reader의 shared cacheline atomic operation을 없애고 RCU를 사용해 read-mostly workload를 빠르게 만드는 percpu rw semaphore를 설명합니다.

Source pathDocumentation/locking/percpu-rw-semaphore.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

매우 싼 reader와 매우 비싼 writer

percpu-rw-semaphore.rst:1-17

일반 rw semaphore는 여러 CPU가 read count가 들어 있는 같은 cacheline을 atomic하게 갱신하여 L1 cache 사이를 계속 이동시킵니다. percpu rw semaphore는 reader path에 per-CPU 상태와 RCU를 사용해 lock과 unlock에서 atomic instruction을 피합니다.

대가로 writer는 synchronize_rcu()를 호출하여 기존 reader가 모두 빠져나오기를 기다립니다. 이 대기는 수백 millisecond까지 갈 수 있습니다. Read가 압도적으로 많고 write latency를 길게 허용할 수 있는 데이터에만 맞습니다.

수명과 API

percpu-rw-semaphore.rst:18-29
struct percpu_rw_semaphore sem;

ret = percpu_init_rwsem(&sem);
if (ret)
    return -ENOMEM;

percpu_down_read(&sem);
/* read-side */
percpu_up_read(&sem);

percpu_down_write(&sem);
/* write-side */
percpu_up_write(&sem);

percpu_free_rwsem(&sem);

percpu_init_rwsem()은 per-CPU storage를 할당하므로 -ENOMEM을 처리해야 합니다. 마지막 사용자가 사라지고 진행 중인 reader와 writer가 없어진 뒤 percpu_free_rwsem()을 호출해야 memory leak과 use-after-free를 피할 수 있습니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 ====================
2 Percpu rw semaphores
3 ====================
4
5 Percpu rw semaphores is a new read-write semaphore design that is
6 optimized for locking for reading.
7
8 The problem with traditional read-write semaphores is that when multiple
9 cores take the lock for reading, the cache line containing the semaphore
10 is bouncing between L1 caches of the cores, causing performance
11 degradation.
12
13 Locking for reading is very fast, it uses RCU and it avoids any atomic
14 instruction in the lock and unlock path. On the other hand, locking for
15 writing is very expensive, it calls synchronize_rcu() that can take
16 hundreds of milliseconds.
17
18 The lock is declared with "struct percpu_rw_semaphore" type.
19 The lock is initialized with percpu_init_rwsem, it returns 0 on success
20 and -ENOMEM on allocation failure.
21 The lock must be freed with percpu_free_rwsem to avoid memory leak.
22
23 The lock is locked for read with percpu_down_read, percpu_up_read and
24 for write with percpu_down_write, percpu_up_write.
25
26 The idea of using RCU for optimized rw-lock was introduced by
27 Eric Dumazet <eric.dumazet@gmail.com>.
28 The code was written by Mikulas Patocka <mpatocka@redhat.com>
29

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

Percpu rw semaphore

1-17

Percpu rw semaphore는 read lock 동작에 최적화한 새로운 read-write semaphore 설계다.

전통적인 read-write semaphore에서는 여러 core가 read lock을 획득할 때 semaphore가 들어 있는 cache line이 각 core의 L1 cache 사이를 계속 이동한다. 이 cache-line bouncing 때문에 성능이 저하된다.

Percpu rw semaphore의 read lock은 매우 빠르다. RCU를 사용하며 lock과 unlock 경로에서 atomic instruction을 사용하지 않는다. 반면 write lock은 매우 비싸다. 수백 millisecond가 걸릴 수 있는 synchronize_rcu()를 호출하기 때문이다.

선언, 초기화와 lock API

19-29

Lock은 struct percpu_rw_semaphore 형식으로 선언한다. percpu_init_rwsem()으로 초기화하며, 성공하면 0을 반환하고 memory allocation에 실패하면 -ENOMEM을 반환한다. Memory leak을 막으려면 percpu_free_rwsem()으로 반드시 해제해야 한다.

Read lock에는 percpu_down_read()와 percpu_up_read()를 사용한다. Write lock에는 percpu_down_write()와 percpu_up_write()를 사용한다.

RCU를 이용해 rw-lock을 최적화하는 발상은 Eric Dumazet이 제안했으며, Mikulas Patocka가 코드를 작성했다.