NOTE:
This is a version of Documentation/memory-barriers.txt translated into Korean.
This document is maintained by SeongJae Park <sj38.park@gmail.com>.
If you find any difference between this document and the original file or
a problem with the translation, please contact the maintainer of this file.
Please also note that the purpose of this file is to be easier to
read for non English (read: Korean) speakers and is not intended as
a fork. So if you have any comments or updates for this file please
update the original English file first. The English version is
definitive, and readers should look there if they have any doubt.
===================================
์ด ๋ฌธ์๋
Documentation/memory-barriers.txt
์ ํ๊ธ ๋ฒ์ญ์
๋๋ค.
์ญ์๏ผ ๋ฐ์ฑ์ฌ <sj38.park@gmail.com>
===================================
=========================
๋ฆฌ๋
์ค ์ปค๋ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด
=========================
์ ์: David Howells <dhowells@redhat.com>
Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Will Deacon <will.deacon@arm.com>
Peter Zijlstra <peterz@infradead.org>
========
๋ฉด์ฑ
์กฐํญ
========
์ด ๋ฌธ์๋ ๋ช
์ธ์๊ฐ ์๋๋๋ค; ์ด ๋ฌธ์๋ ์๋ฒฝํ์ง ์์๋ฐ, ๊ฐ๊ฒฐ์ฑ์ ์ํด ์๋๋
๋ถ๋ถ๋ ์๊ณ , ์๋ํ์ง ์์์ง๋ง ์ฌ๋์ ์ํด ์ฐ์๋ค๋ณด๋ ๋ถ์์ ํ ๋ถ๋ถ๋ ์์ต๋๋ค.
์ด ๋ฌธ์๋ ๋ฆฌ๋
์ค์์ ์ ๊ณตํ๋ ๋ค์ํ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ค์ ์ฌ์ฉํ๊ธฐ ์ํ
์๋ด์์
๋๋ค๋ง, ๋ญ๊ฐ ์ด์ํ๋ค ์ถ์ผ๋ฉด (๊ทธ๋ฐ๊ฒ ๋ง์ ๊ฒ๋๋ค) ์ง๋ฌธ์ ๋ถํ๋๋ฆฝ๋๋ค.
๋ค์ ๋งํ์ง๋ง, ์ด ๋ฌธ์๋ ๋ฆฌ๋
์ค๊ฐ ํ๋์จ์ด์ ๊ธฐ๋ํ๋ ์ฌํญ์ ๋ํ ๋ช
์ธ์๊ฐ
์๋๋๋ค.
์ด ๋ฌธ์์ ๋ชฉ์ ์ ๋๊ฐ์ง์
๋๋ค:
(1) ์ด๋ค ํน์ ๋ฐฐ๋ฆฌ์ด์ ๋ํด ๊ธฐ๋ํ ์ ์๋ ์ต์ํ์ ๊ธฐ๋ฅ์ ๋ช
์ธํ๊ธฐ ์ํด์,
๊ทธ๋ฆฌ๊ณ
(2) ์ฌ์ฉ ๊ฐ๋ฅํ ๋ฐฐ๋ฆฌ์ด๋ค์ ๋ํด ์ด๋ป๊ฒ ์ฌ์ฉํด์ผ ํ๋์ง์ ๋ํ ์๋ด๋ฅผ ์ ๊ณตํ๊ธฐ
์ํด์.
์ด๋ค ์ํคํ
์ณ๋ ํน์ ํ ๋ฐฐ๋ฆฌ์ด๋ค์ ๋ํด์๋ ์ฌ๊ธฐ์ ์ด์ผ๊ธฐํ๋ ์ต์ํ์
์๊ตฌ์ฌํญ๋ค๋ณด๋ค ๋ง์ ๊ธฐ๋ฅ์ ์ ๊ณตํ ์๋ ์์ต๋๋ค๋ง, ์ฌ๊ธฐ์ ์ด์ผ๊ธฐํ๋
์๊ตฌ์ฌํญ๋ค์ ์ถฉ์กฑํ์ง ์๋ ์ํคํ
์ณ๊ฐ ์๋ค๋ฉด ๊ทธ ์ํคํ
์ณ๊ฐ ์๋ชป๋ ๊ฒ์ด๋ ์ ์
์์๋์๊ธฐ ๋ฐ๋๋๋ค.
๋ํ, ํน์ ์ํคํ
์ณ์์ ์ผ๋ถ ๋ฐฐ๋ฆฌ์ด๋ ํด๋น ์ํคํ
์ณ์ ํน์ํ ๋์ ๋ฐฉ์์ผ๋ก ์ธํด
ํด๋น ๋ฐฐ๋ฆฌ์ด์ ๋ช
์์ ์ฌ์ฉ์ด ๋ถํ์ํด์ no-op ์ด ๋ ์๋ ์์์ ์์๋์๊ธฐ
๋ฐ๋๋๋ค.
์ญ์: ๋ณธ ๋ฒ์ญ ์ญ์ ์๋ฒฝํ์ง ์์๋ฐ, ์ด ์ญ์ ๋ถ๋ถ์ ์ผ๋ก๋ ์๋๋ ๊ฒ์ด๊ธฐ๋
ํฉ๋๋ค. ์ฌํ ๊ธฐ์ ๋ฌธ์๋ค์ด ๊ทธ๋ ๋ฏ ์๋ฒฝํ ์ดํด๋ฅผ ์ํด์๋ ๋ฒ์ญ๋ฌธ๊ณผ ์๋ฌธ์ ํจ๊ป
์ฝ์ผ์๋ ๋ฒ์ญ๋ฌธ์ ํ๋์ ๊ฐ์ด๋๋ก ํ์ฉํ์๊ธธ ์ถ์ฒ๋๋ฆฌ๋ฉฐ, ๋ฐ๊ฒฌ๋๋ ์ค์ญ ๋ฑ์
๋ํด์๋ ์ธ์ ๋ ์๊ฒฌ์ ๋ถํ๋๋ฆฝ๋๋ค. ๊ณผํ ๋ฒ์ญ์ผ๋ก ์ธํ ์คํด๋ฅผ ์ต์ํํ๊ธฐ ์ํด
์ ๋งคํ ๋ถ๋ถ์ด ์์ ๊ฒฝ์ฐ์๋ ์ด์ํจ์ด ์๋๋ผ๋ ์๋์ ์ฉ์ด๋ฅผ ์ฐจ์ฉํฉ๋๋ค.
=====
๋ชฉ์ฐจ:
=====
(*) ์ถ์ ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค ๋ชจ๋ธ.
- ๋๋ฐ์ด์ค ์คํผ๋ ์ด์
.
- ๋ณด์ฅ์ฌํญ.
(*) ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ ๋ฌด์์ธ๊ฐ?
- ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด์ ์ข
๋ฅ.
- ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด์ ๋ํด ๊ฐ์ ํด์ ์๋ ๊ฒ.
- ๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด.
- ์ปจํธ๋กค ์์กด์ฑ.
- SMP ๋ฐฐ๋ฆฌ์ด ์ง๋ง์ถ๊ธฐ.
- ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด ์ํ์ค์ ์.
- ์ฝ๊ธฐ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด vs ๋ก๋ ์์ธก.
- ์ดํ์ฑ
(*) ๋ช
์์ ์ปค๋ ๋ฐฐ๋ฆฌ์ด.
- ์ปดํ์ผ๋ฌ ๋ฐฐ๋ฆฌ์ด.
- CPU ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด.
- MMIO ์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด.
(*) ์๋ฌต์ ์ปค๋ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด.
- ๋ฝ Acquisition ํจ์.
- ์ธํฐ๋ฝํธ ๋นํ์ฑํ ํจ์.
- ์ฌ๋ฆฝ๊ณผ ์จ์ดํฌ์
ํจ์.
- ๊ทธ์ธ์ ํจ์๋ค.
(*) CPU ๊ฐ ACQUIRING ๋ฐฐ๋ฆฌ์ด์ ํจ๊ณผ.
- Acquire vs ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค.
- Acquire vs I/O ์ก์ธ์ค.
(*) ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๊ฐ ํ์ํ ๊ณณ
- ํ๋ก์ธ์๊ฐ ์ํธ ์์ฉ.
- ์ดํ ๋ฏน ์คํผ๋ ์ด์
.
- ๋๋ฐ์ด์ค ์ก์ธ์ค.
- ์ธํฐ๋ฝํธ.
(*) ์ปค๋ I/O ๋ฐฐ๋ฆฌ์ด์ ํจ๊ณผ.
(*) ๊ฐ์ ๋๋ ๊ฐ์ฅ ์ํ๋ ์คํ ์์ ๋ชจ๋ธ.
(*) CPU ์บ์์ ์ํฅ.
- ์บ์ ์ผ๊ด์ฑ.
- ์บ์ ์ผ๊ด์ฑ vs DMA.
- ์บ์ ์ผ๊ด์ฑ vs MMIO.
(*) CPU ๋ค์ด ์ ์ง๋ฅด๋ ์ผ๋ค.
- ๊ทธ๋ฆฌ๊ณ , Alpha ๊ฐ ์๋ค.
- ๊ฐ์ ๋จธ์ ๊ฒ์คํธ.
(*) ์ฌ์ฉ ์.
- ์ํ์ ๋ฒํผ.
(*) ์ฐธ๊ณ ๋ฌธํ.
=======================
์ถ์ ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค ๋ชจ๋ธ
=======================
๋ค์๊ณผ ๊ฐ์ด ์ถ์ํ๋ ์์คํ
๋ชจ๋ธ์ ์๊ฐํด ๋ด
์๋ค:
: :
: :
: :
+-------+ : +--------+ : +-------+
| | : | | : | |
| | : | | : | |
| CPU 1 |<----->| Memory |<----->| CPU 2 |
| | : | | : | |
| | : | | : | |
+-------+ : +--------+ : +-------+
^ : ^ : ^
| : | : |
| : | : |
| : v : |
| : +--------+ : |
| : | | : |
| : | | : |
+---------->| Device |<----------+
: | | :
: | | :
: +--------+ :
: :
ํ๋ก๊ทธ๋จ์ ์ฌ๋ฌ ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค ์คํผ๋ ์ด์
์ ๋ฐ์์ํค๊ณ , ๊ฐ๊ฐ์ CPU ๋ ๊ทธ๋ฐ
ํ๋ก๊ทธ๋จ๋ค์ ์คํํฉ๋๋ค. ์ถ์ํ๋ CPU ๋ชจ๋ธ์์ ๋ฉ๋ชจ๋ฆฌ ์คํผ๋ ์ด์
๋ค์ ์์๋
๋งค์ฐ ์ํ๋์ด ์๊ณ , CPU ๋ ํ๋ก๊ทธ๋จ์ด ์ธ๊ณผ๊ด๊ณ๋ฅผ ์ด๊ธฐ์ง ์๋ ์ํ๋ก ๊ด๋ฆฌ๋๋ค๊ณ
๋ณด์ผ ์๋ง ์๋ค๋ฉด ๋ฉ๋ชจ๋ฆฌ ์คํผ๋ ์ด์
์ ์์ ์ด ์ํ๋ ์ด๋ค ์์๋๋ก๋ ์ฌ๋ฐฐ์นํด
๋์์ํฌ ์ ์์ต๋๋ค. ๋น์ทํ๊ฒ, ์ปดํ์ผ๋ฌ ๋ํ ํ๋ก๊ทธ๋จ์ ์ ์์ ๋์์ ํด์น์ง
์๋ ํ๋ ๋ด์์๋ ์ด๋ค ์์๋ก๋ ์์ ์ด ์ํ๋ ๋๋ก ์ธ์คํธ๋ญ์
์ ์ฌ๋ฐฐ์น ํ ์
์์ต๋๋ค.
๋ฐ๋ผ์ ์์ ๋ค์ด์ด๊ทธ๋จ์์ ํ CPU๊ฐ ๋์์ํค๋ ๋ฉ๋ชจ๋ฆฌ ์คํผ๋ ์ด์
์ด ๋ง๋ค์ด๋ด๋
๋ณํ๋ ํด๋น ์คํผ๋ ์ด์
์ด CPU ์ ์์คํ
์ ๋ค๋ฅธ ๋ถ๋ถ๋ค ์ฌ์ด์ ์ธํฐํ์ด์ค(์ ์ )๋ฅผ
์ง๋๊ฐ๋ฉด์ ์์คํ
์ ๋๋จธ์ง ๋ถ๋ถ๋ค์ ์ธ์ง๋ฉ๋๋ค.
์๋ฅผ ๋ค์ด, ๋ค์์ ์ผ๋ จ์ ์ด๋ฒคํธ๋ค์ ์๊ฐํด ๋ด
์๋ค:
CPU 1 CPU 2
=============== ===============
{ A == 1; B == 2 }
A = 3; x = B;
B = 4; y = A;
๋ค์ด์ด๊ทธ๋จ์ ๊ฐ์ด๋ฐ์ ์์นํ ๋ฉ๋ชจ๋ฆฌ ์์คํ
์ ๋ณด์ฌ์ง๊ฒ ๋๋ ์ก์ธ์ค๋ค์ ๋ค์์ ์ด
24๊ฐ์ ์กฐํฉ์ผ๋ก ์ฌ๊ตฌ์ฑ๋ ์ ์์ต๋๋ค:
STORE A=3, STORE B=4, y=LOAD A->3, x=LOAD B->4
STORE A=3, STORE B=4, x=LOAD B->4, y=LOAD A->3
STORE A=3, y=LOAD A->3, STORE B=4, x=LOAD B->4
STORE A=3, y=LOAD A->3, x=LOAD B->2, STORE B=4
STORE A=3, x=LOAD B->2, STORE B=4, y=LOAD A->3
STORE A=3, x=LOAD B->2, y=LOAD A->3, STORE B=4
STORE B=4, STORE A=3, y=LOAD A->3, x=LOAD B->4
STORE B=4, ...
...
๋ฐ๋ผ์ ๋ค์์ ๋ค๊ฐ์ง ์กฐํฉ์ ๊ฐ๋ค์ด ๋์ฌ ์ ์์ต๋๋ค:
x == 2, y == 1
x == 2, y == 3
x == 4, y == 1
x == 4, y == 3
ํ๋ฐ ๋ ๋์๊ฐ์, ํ CPU ๊ฐ ๋ฉ๋ชจ๋ฆฌ ์์คํ
์ ๋ฐ์ํ ์คํ ์ด ์คํผ๋ ์ด์
๋ค์ ๊ฒฐ๊ณผ๋
๋ค๋ฅธ CPU ์์์ ๋ก๋ ์คํผ๋ ์ด์
์ ํตํด ์ธ์ง๋๋๋ฐ, ์ด ๋ ์คํ ์ด๊ฐ ๋ฐ์๋ ์์์
๋ค๋ฅธ ์์๋ก ์ธ์ง๋ ์๋ ์์ต๋๋ค.
์๋ก, ์๋์ ์ผ๋ จ์ ์ด๋ฒคํธ๋ค์ ์๊ฐํด ๋ด
์๋ค:
CPU 1 CPU 2
=============== ===============
{ A == 1, B == 2, C == 3, P == &A, Q == &C }
B = 4; Q = P;
P = &B D = *Q;
D ๋ก ์ฝํ์ง๋ ๊ฐ์ CPU 2 ์์ P ๋ก๋ถํฐ ์ฝํ์ง ์ฃผ์๊ฐ์ ์์กด์ ์ด๊ธฐ ๋๋ฌธ์ ์ฌ๊ธฐ์
๋ถ๋ช
ํ ๋ฐ์ดํฐ ์์กด์ฑ์ด ์์ต๋๋ค. ํ์ง๋ง ์ด ์ด๋ฒคํธ๋ค์ ์คํ ๊ฒฐ๊ณผ๋ก๋ ์๋์
๊ฒฐ๊ณผ๋ค์ด ๋ชจ๋ ๋ํ๋ ์ ์์ต๋๋ค:
(Q == &A) and (D == 1)
(Q == &B) and (D == 2)
(Q == &B) and (D == 4)
CPU 2 ๋ *Q ์ ๋ก๋๋ฅผ ์์ฒญํ๊ธฐ ์ ์ P ๋ฅผ Q ์ ๋ฃ๊ธฐ ๋๋ฌธ์ D ์ C ๋ฅผ ์ง์ด๋ฃ๋
์ผ์ ์์์ ์์๋์ธ์.
๋๋ฐ์ด์ค ์คํผ๋ ์ด์
-------------------
์ผ๋ถ ๋๋ฐ์ด์ค๋ ์์ ์ ์ปจํธ๋กค ์ธํฐํ์ด์ค๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ํน์ ์์ญ์ผ๋ก ๋งคํํด์
์ ๊ณตํ๋๋ฐ(Memory mapped I/O), ํด๋น ์ปจํธ๋กค ๋ ์ง์คํฐ์ ์ ๊ทผํ๋ ์์๋ ๋งค์ฐ
์ค์ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์ด๋๋ ์ค ํฌํธ ๋ ์ง์คํฐ (A) ์ ๋ฐ์ดํฐ ํฌํธ ๋ ์ง์คํฐ (D)
๋ฅผ ํตํด ์ ๊ทผ๋๋ ๋ด๋ถ ๋ ์ง์คํฐ ์งํฉ์ ๊ฐ๋ ์ด๋๋ท ์นด๋๋ฅผ ์๊ฐํด ๋ด
์๋ค. ๋ด๋ถ์
5๋ฒ ๋ ์ง์คํฐ๋ฅผ ์ฝ๊ธฐ ์ํด ๋ค์์ ์ฝ๋๊ฐ ์ฌ์ฉ๋ ์ ์์ต๋๋ค:
*A = 5;
x = *D;
ํ์ง๋ง, ์ด๊ฑด ๋ค์์ ๋ ์กฐํฉ ์ค ํ๋๋ก ๋ง๋ค์ด์ง ์ ์์ต๋๋ค:
STORE *A = 5, x = LOAD *D
x = LOAD *D, STORE *A = 5
๋๋ฒ์งธ ์กฐํฉ์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด์จ _ํ์_ ์ฃผ์๋ฅผ ์ค์ ํ๋ฏ๋ก, ์ค๋์์ ์ผ์ผํฌ ๊ฒ๋๋ค.
๋ณด์ฅ์ฌํญ
--------
CPU ์๊ฒ ๊ธฐ๋ํ ์ ์๋ ์ต์ํ์ ๋ณด์ฅ์ฌํญ ๋ช๊ฐ์ง๊ฐ ์์ต๋๋ค:
(*) ์ด๋ค CPU ๋ , ์์กด์ฑ์ด ์กด์ฌํ๋ ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค๋ค์ ํด๋น CPU ์์ ์๊ฒ
์์ด์๋ ์์๋๋ก ๋ฉ๋ชจ๋ฆฌ ์์คํ
์ ์ํ ์์ฒญ๋ฉ๋๋ค. ์ฆ, ๋ค์์ ๋ํด์:
Q = READ_ONCE(P); smp_read_barrier_depends(); D = READ_ONCE(*Q);
CPU ๋ ๋ค์๊ณผ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ ์คํผ๋ ์ด์
์ํ์ค๋ฅผ ์ํ ์์ฒญํฉ๋๋ค:
Q = LOAD P, D = LOAD *Q
๊ทธ๋ฆฌ๊ณ ๊ทธ ์ํ์ค ๋ด์์์ ์์๋ ํญ์ ์ง์ผ์ง๋๋ค. ๋๋ถ๋ถ์ ์์คํ
์์
smp_read_barrier_depends() ๋ ์๋ฌด์ผ๋ ์ํ์ง๋ง DEC Alpha ์์๋
๋ช
์์ ์ผ๋ก ์ฌ์ฉ๋์ด์ผ ํฉ๋๋ค. ๋ณดํต์ ๊ฒฝ์ฐ์๋ smp_read_barrier_depends()
๋ฅผ ์ง์ ์ฌ์ฉํ๋ ๋์ rcu_dereference() ๊ฐ์ ๊ฒ๋ค์ ์ฌ์ฉํด์ผ ํจ์
์์๋์ธ์.
(*) ํน์ CPU ๋ด์์ ๊ฒน์น๋ ์์ญ์ ๋ฉ๋ชจ๋ฆฌ์ ํํด์ง๋ ๋ก๋์ ์คํ ์ด ๋ค์ ํด๋น
CPU ์์์๋ ์์๊ฐ ๋ฐ๋์ง ์์ ๊ฒ์ผ๋ก ๋ณด์ฌ์ง๋๋ค. ์ฆ, ๋ค์์ ๋ํด์:
a = READ_ONCE(*X); WRITE_ONCE(*X, b);
CPU ๋ ๋ค์์ ๋ฉ๋ชจ๋ฆฌ ์คํผ๋ ์ด์
์ํ์ค๋ง์ ๋ฉ๋ชจ๋ฆฌ์ ์์ฒญํ ๊ฒ๋๋ค:
a = LOAD *X, STORE *X = b
๊ทธ๋ฆฌ๊ณ ๋ค์์ ๋ํด์๋:
WRITE_ONCE(*X, c); d = READ_ONCE(*X);
CPU ๋ ๋ค์์ ์ํ ์์ฒญ๋ง์ ๋ง๋ค์ด ๋
๋๋ค:
STORE *X = c, d = LOAD *X
(๋ก๋ ์คํผ๋ ์ด์
๊ณผ ์คํ ์ด ์คํผ๋ ์ด์
์ด ๊ฒน์น๋ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ๋ํด
์ํ๋๋ค๋ฉด ํด๋น ์คํผ๋ ์ด์
๋ค์ ๊ฒน์น๋ค๊ณ ํํ๋ฉ๋๋ค).
๊ทธ๋ฆฌ๊ณ _๋ฐ๋์_ ๋๋ _์ ๋๋ก_ ๊ฐ์ ํ๊ฑฐ๋ ๊ฐ์ ํ์ง ๋ง์์ผ ํ๋ ๊ฒ๋ค์ด ์์ต๋๋ค:
(*) ์ปดํ์ผ๋ฌ๊ฐ READ_ONCE() ๋ WRITE_ONCE() ๋ก ๋ณดํธ๋์ง ์์ ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค๋ฅผ
๋น์ ์ด ์ํ๋ ๋๋ก ํ ๊ฒ์ด๋ผ๋ ๊ฐ์ ์ _์ ๋๋ก_ ํด์ ์๋ฉ๋๋ค. ๊ทธ๊ฒ๋ค์ด
์๋ค๋ฉด, ์ปดํ์ผ๋ฌ๋ ์ปดํ์ผ๋ฌ ๋ฐฐ๋ฆฌ์ด ์น์
์์ ๋ค๋ฃจ๊ฒ ๋ , ๋ชจ๋ "์ฐฝ์์ ์ธ"
๋ณ๊ฒฝ๋ค์ ๋ง๋ค์ด๋ผ ๊ถํ์ ๊ฐ๊ฒ ๋ฉ๋๋ค.
(*) ๊ฐ๋ณ์ ์ธ ๋ก๋์ ์คํ ์ด๋ค์ด ์ฃผ์ด์ง ์์๋๋ก ์์ฒญ๋ ๊ฒ์ด๋ผ๋ ๊ฐ์ ์ _์ ๋๋ก_
ํ์ง ๋ง์์ผ ํฉ๋๋ค. ์ด ๋ง์ ๊ณง:
X = *A; Y = *B; *D = Z;
๋ ๋ค์์ ๊ฒ๋ค ์ค ์ด๋ ๊ฒ์ผ๋ก๋ ๋ง๋ค์ด์ง ์ ์๋ค๋ ์๋ฏธ์
๋๋ค:
X = LOAD *A, Y = LOAD *B, STORE *D = Z
X = LOAD *A, STORE *D = Z, Y = LOAD *B
Y = LOAD *B, X = LOAD *A, STORE *D = Z
Y = LOAD *B, STORE *D = Z, X = LOAD *A
STORE *D = Z, X = LOAD *A, Y = LOAD *B
STORE *D = Z, Y = LOAD *B, X = LOAD *A
(*) ๊ฒน์น๋ ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค๋ค์ ํฉ์ณ์ง๊ฑฐ๋ ๋ฒ๋ ค์ง ์ ์์์ _๋ฐ๋์_ ๊ฐ์ ํด์ผ
ํฉ๋๋ค. ๋ค์์ ์ฝ๋๋:
X = *A; Y = *(A + 4);
๋ค์์ ๊ฒ๋ค ์ค ๋ญ๋ ๋ ์ ์์ต๋๋ค:
X = LOAD *A; Y = LOAD *(A + 4);
Y = LOAD *(A + 4); X = LOAD *A;
{X, Y} = LOAD {*A, *(A + 4) };
๊ทธ๋ฆฌ๊ณ :
*A = X; *(A + 4) = Y;
๋ ๋ค์ ์ค ๋ญ๋ ๋ ์ ์์ต๋๋ค:
STORE *A = X; STORE *(A + 4) = Y;
STORE *(A + 4) = Y; STORE *A = X;
STORE {*A, *(A + 4) } = {X, Y};
๊ทธ๋ฆฌ๊ณ ๋ณด์ฅ์ฌํญ์ ๋ฐ๋๋๋ ๊ฒ๋ค(anti-guarantees)์ด ์์ต๋๋ค:
(*) ์ด ๋ณด์ฅ์ฌํญ๋ค์ bitfield ์๋ ์ ์ฉ๋์ง ์๋๋ฐ, ์ปดํ์ผ๋ฌ๋ค์ bitfield ๋ฅผ
์์ ํ๋ ์ฝ๋๋ฅผ ์์ฑํ ๋ ์์์ฑ ์๋(non-atomic) ์ฝ๊ณ -์์ ํ๊ณ -์ฐ๋
์ธ์คํธ๋ญ์
๋ค์ ์กฐํฉ์ ๋ง๋๋ ๊ฒฝ์ฐ๊ฐ ๋ง๊ธฐ ๋๋ฌธ์
๋๋ค. ๋ณ๋ ฌ ์๊ณ ๋ฆฌ์ฆ์
๋๊ธฐํ์ bitfield ๋ฅผ ์ฌ์ฉํ๋ ค ํ์ง ๋ง์ญ์์ค.
(*) bitfield ๋ค์ด ์ฌ๋ฌ ๋ฝ์ผ๋ก ๋ณดํธ๋๋ ๊ฒฝ์ฐ๋ผ ํ๋๋ผ๋, ํ๋์ bitfield ์
๋ชจ๋ ํ๋๋ค์ ํ๋์ ๋ฝ์ผ๋ก ๋ณดํธ๋์ด์ผ ํฉ๋๋ค. ๋ง์ฝ ํ bitfield ์ ๋
ํ๋๊ฐ ์๋ก ๋ค๋ฅธ ๋ฝ์ผ๋ก ๋ณดํธ๋๋ค๋ฉด, ์ปดํ์ผ๋ฌ์ ์์์ฑ ์๋
์ฝ๊ณ -์์ ํ๊ณ -์ฐ๋ ์ธ์คํธ๋ญ์
์กฐํฉ์ ํ ํ๋์์ ์
๋ฐ์ดํธ๊ฐ ๊ทผ์ฒ์
ํ๋์๋ ์ํฅ์ ๋ผ์น๊ฒ ํ ์ ์์ต๋๋ค.
(*) ์ด ๋ณด์ฅ์ฌํญ๋ค์ ์ ์ ํ๊ฒ ์ ๋ ฌ๋๊ณ ํฌ๊ธฐ๊ฐ ์กํ ์ค์นผ๋ผ ๋ณ์๋ค์ ๋ํด์๋ง
์ ์ฉ๋ฉ๋๋ค. "์ ์ ํ๊ฒ ํฌ๊ธฐ๊ฐ ์กํ" ์ด๋ผํจ์ ํ์ฌ๋ก์จ๋ "char", "short",
"int" ๊ทธ๋ฆฌ๊ณ "long" ๊ณผ ๊ฐ์ ํฌ๊ธฐ์ ๋ณ์๋ค์ ์๋ฏธํฉ๋๋ค. "์ ์ ํ๊ฒ ์ ๋ ฌ๋"
์ ์์ฐ์ค๋ฐ ์ ๋ ฌ์ ์๋ฏธํ๋๋ฐ, ๋ฐ๋ผ์ "char" ์ ๋ํด์๋ ์๋ฌด ์ ์ฝ์ด ์๊ณ ,
"short" ์ ๋ํด์๋ 2๋ฐ์ดํธ ์ ๋ ฌ์, "int" ์๋ 4๋ฐ์ดํธ ์ ๋ ฌ์, ๊ทธ๋ฆฌ๊ณ
"long" ์ ๋ํด์๋ 32-bit ์์คํ
์ธ์ง 64-bit ์์คํ
์ธ์ง์ ๋ฐ๋ผ 4๋ฐ์ดํธ ๋๋
8๋ฐ์ดํธ ์ ๋ ฌ์ ์๋ฏธํฉ๋๋ค. ์ด ๋ณด์ฅ์ฌํญ๋ค์ C11 ํ์ค์์ ์๊ฐ๋์์ผ๋ฏ๋ก,
C11 ์ ์ ์ค๋๋ ์ปดํ์ผ๋ฌ(์๋ฅผ ๋ค์ด, gcc 4.6) ๋ฅผ ์ฌ์ฉํ ๋์ ์ฃผ์ํ์๊ธฐ
๋ฐ๋๋๋ค. ํ์ค์ ์ด ๋ณด์ฅ์ฌํญ๋ค์ "memory location" ์ ์ ์ํ๋ 3.14
์น์
์ ๋ค์๊ณผ ๊ฐ์ด ์ค๋ช
๋์ด ์์ต๋๋ค:
(์ญ์: ์ธ์ฉ๋ฌธ์ด๋ฏ๋ก ๋ฒ์ญํ์ง ์์ต๋๋ค)
memory location
either an object of scalar type, or a maximal sequence
of adjacent bit-fields all having nonzero width
NOTE 1: Two threads of execution can update and access
separate memory locations without interfering with
each other.
NOTE 2: A bit-field and an adjacent non-bit-field member
are in separate memory locations. The same applies
to two bit-fields, if one is declared inside a nested
structure declaration and the other is not, or if the two
are separated by a zero-length bit-field declaration,
or if they are separated by a non-bit-field member
declaration. It is not safe to concurrently update two
bit-fields in the same structure if all members declared
between them are also bit-fields, no matter what the
sizes of those intervening bit-fields happen to be.
=========================
๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ ๋ฌด์์ธ๊ฐ?
=========================
์์์ ๋ดค๋ฏ์ด, ์ํธ๊ฐ ์์กด์ฑ์ด ์๋ ๋ฉ๋ชจ๋ฆฌ ์คํผ๋ ์ด์
๋ค์ ์ค์ ๋ก๋ ๋ฌด์์์
์์๋ก ์ํ๋ ์ ์์ผ๋ฉฐ, ์ด๋ CPU ์ CPU ๊ฐ์ ์ํธ์์ฉ์ด๋ I/O ์ ๋ฌธ์ ๊ฐ ๋ ์
์์ต๋๋ค. ๋ฐ๋ผ์ ์ปดํ์ผ๋ฌ์ CPU ๊ฐ ์์๋ฅผ ๋ฐ๊พธ๋๋ฐ ์ ์ฝ์ ๊ฑธ ์ ์๋๋ก ๊ฐ์
ํ
์ ์๋ ์ด๋ค ๋ฐฉ๋ฒ์ด ํ์ํฉ๋๋ค.
๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ ๊ทธ๋ฐ ๊ฐ์
์๋จ์
๋๋ค. ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ ๋ฐฐ๋ฆฌ์ด๋ฅผ ์ฌ์ด์ ๋ ์๊ณผ
๋ค ์์ธก์ ๋ฉ๋ชจ๋ฆฌ ์คํผ๋ ์ด์
๋ค ๊ฐ์ ๋ถ๋ถ์ ์์๊ฐ ์กด์ฌํ๋๋ก ํ๋ ํจ๊ณผ๋ฅผ ์ค๋๋ค.
์์คํ
์ CPU ๋ค๊ณผ ์ฌ๋ฌ ๋๋ฐ์ด์ค๋ค์ ์ฑ๋ฅ์ ์ฌ๋ฆฌ๊ธฐ ์ํด ๋ช
๋ น์ด ์ฌ๋ฐฐ์น, ์คํ
์ ์, ๋ฉ๋ชจ๋ฆฌ ์คํผ๋ ์ด์
๋ค์ ์กฐํฉ, ์์ธก์ ๋ก๋(speculative load), ๋ธ๋์น
์์ธก(speculative branch prediction), ๋ค์ํ ์ข
๋ฅ์ ์บ์ฑ(caching) ๋ฑ์ ๋ค์ํ
ํธ๋ฆญ์ ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ ์ด๋ฐ ๊ฐ์ ๋ ฅ์ ์ค์ํฉ๋๋ค. ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ค์ ์ด๋ฐ
ํธ๋ฆญ๋ค์ ๋ฌดํจ๋ก ํ๊ฑฐ๋ ์ต์ ํ๋ ๋ชฉ์ ์ผ๋ก ์ฌ์ฉ๋์ด์ ธ์ ์ฝ๋๊ฐ ์ฌ๋ฌ CPU ์
๋๋ฐ์ด์ค๋ค ๊ฐ์ ์ํธ์์ฉ์ ์ ์์ ์ผ๋ก ์ ์ดํ ์ ์๊ฒ ํด์ค๋๋ค.
๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด์ ์ข
๋ฅ
--------------------
๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ ๋ค๊ฐ์ ๊ธฐ๋ณธ ํ์
์ผ๋ก ๋ถ๋ฅ๋ฉ๋๋ค:
(1) ์ฐ๊ธฐ (๋๋ ์คํ ์ด) ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด.
์ฐ๊ธฐ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ ์์คํ
์ ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ค์ ํด๋น ๋ฐฐ๋ฆฌ์ด๋ณด๋ค ์์
๋ช
์๋ ๋ชจ๋ STORE ์คํผ๋ ์ด์
๋ค์ด ํด๋น ๋ฐฐ๋ฆฌ์ด ๋ค์ ๋ช
์๋ ๋ชจ๋ STORE
์คํผ๋ ์ด์
๋ค๋ณด๋ค ๋จผ์ ์ํ๋ ๊ฒ์ผ๋ก ๋ณด์ผ ๊ฒ์ ๋ณด์ฅํฉ๋๋ค.
์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด๋ ์คํ ์ด ์คํผ๋ ์ด์
๋ค์ ๋ํ ๋ถ๋ถ์ ์์ ์ธ์ฐ๊ธฐ์
๋๋ค; ๋ก๋
์คํผ๋ ์ด์
๋ค์ ๋ํด์๋ ์ด๋ค ์ํฅ๋ ๋ผ์น์ง ์์ต๋๋ค.
CPU ๋ ์๊ฐ์ ํ๋ฆ์ ๋ฐ๋ผ ๋ฉ๋ชจ๋ฆฌ ์์คํ
์ ์ผ๋ จ์ ์คํ ์ด ์คํผ๋ ์ด์
๋ค์
ํ๋์ฉ ์์ฒญํด ์ง์ด๋ฃ์ต๋๋ค. ์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด ์์ ๋ชจ๋ ์คํ ์ด ์คํผ๋ ์ด์
๋ค์
์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด ๋ค์ ๋ชจ๋ ์คํ ์ด ์คํผ๋ ์ด์
๋ค๋ณด๋ค _์์_ ์ํ๋ ๊ฒ๋๋ค.
[!] ์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด๋ค์ ์ฝ๊ธฐ ๋๋ ๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด์ ํจ๊ป ์ง์ ๋ง์ถฐ
์ฌ์ฉ๋์ด์ผ๋ง ํจ์ ์์๋์ธ์; "SMP ๋ฐฐ๋ฆฌ์ด ์ง๋ง์ถ๊ธฐ" ์๋ธ์น์
์ ์ฐธ๊ณ ํ์ธ์.
(2) ๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด.
๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๋ ์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด์ ๋ณด๋ค ์ํ๋ ํํ์
๋๋ค. ๋๊ฐ์ ๋ก๋
์คํผ๋ ์ด์
์ด ์๊ณ ๋๋ฒ์งธ ๊ฒ์ด ์ฒซ๋ฒ์งธ ๊ฒ์ ๊ฒฐ๊ณผ์ ์์กดํ๊ณ ์์ ๋(์:
๋๋ฒ์งธ ๋ก๋๊ฐ ์ฐธ์กฐํ ์ฃผ์๋ฅผ ์ฒซ๋ฒ์งธ ๋ก๋๊ฐ ์ฝ๋ ๊ฒฝ์ฐ), ๋๋ฒ์งธ ๋ก๋๊ฐ ์ฝ์ด์ฌ
๋ฐ์ดํฐ๋ ์ฒซ๋ฒ์งธ ๋ก๋์ ์ํด ๊ทธ ์ฃผ์๊ฐ ์ป์ด์ง๊ธฐ ์ ์ ์
๋ฐ์ดํธ ๋์ด ์์์
๋ณด์ฅํ๊ธฐ ์ํด์ ๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๊ฐ ํ์ํ ์ ์์ต๋๋ค.
๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๋ ์ํธ ์์กด์ ์ธ ๋ก๋ ์คํผ๋ ์ด์
๋ค ์ฌ์ด์ ๋ถ๋ถ์ ์์
์ธ์ฐ๊ธฐ์
๋๋ค; ์คํ ์ด ์คํผ๋ ์ด์
๋ค์ด๋ ๋
๋ฆฝ์ ์ธ ๋ก๋๋ค, ๋๋ ์ค๋ณต๋๋
๋ก๋๋ค์ ๋ํด์๋ ์ด๋ค ์ํฅ๋ ๋ผ์น์ง ์์ต๋๋ค.
(1) ์์ ์ธ๊ธํ๋ฏ์ด, ์์คํ
์ CPU ๋ค์ ๋ฉ๋ชจ๋ฆฌ ์์คํ
์ ์ผ๋ จ์ ์คํ ์ด
์คํผ๋ ์ด์
๋ค์ ๋์ ธ ๋ฃ๊ณ ์์ผ๋ฉฐ, ๊ฑฐ๊ธฐ์ ๊ด์ฌ์ด ์๋ ๋ค๋ฅธ CPU ๋ ๊ทธ
์คํผ๋ ์ด์
๋ค์ ๋ฉ๋ชจ๋ฆฌ ์์คํ
์ด ์คํํ ๊ฒฐ๊ณผ๋ฅผ ์ธ์งํ ์ ์์ต๋๋ค. ์ด์ฒ๋ผ
๋ค๋ฅธ CPU ์ ์คํ ์ด ์คํผ๋ ์ด์
์ ๊ฒฐ๊ณผ์ ๊ด์ฌ์ ๋๊ณ ์๋ CPU ๊ฐ ์ํ ์์ฒญํ
๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๋, ๋ฐฐ๋ฆฌ์ด ์์ ์ด๋ค ๋ก๋ ์คํผ๋ ์ด์
์ด ๋ค๋ฅธ CPU ์์
๋์ ธ ๋ฃ์ ์คํ ์ด ์คํผ๋ ์ด์
๊ณผ ๊ฐ์ ์์ญ์ ํฅํ๋ค๋ฉด, ๊ทธ๋ฐ ์คํ ์ด
์คํผ๋ ์ด์
๋ค์ด ๋ง๋ค์ด๋ด๋ ๊ฒฐ๊ณผ๊ฐ ๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด ๋ค์ ๋ก๋
์คํผ๋ ์ด์
๋ค์๊ฒ๋ ๋ณด์ผ ๊ฒ์ ๋ณด์ฅํฉ๋๋ค.
์ด ์์ ์ธ์ฐ๊ธฐ ์ ์ฝ์ ๋ํ ๊ทธ๋ฆผ์ ๋ณด๊ธฐ ์ํด์ "๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด ์ํ์ค์ ์"
์๋ธ์น์
์ ์ฐธ๊ณ ํ์๊ธฐ ๋ฐ๋๋๋ค.
[!] ์ฒซ๋ฒ์งธ ๋ก๋๋ ๋ฐ๋์ _๋ฐ์ดํฐ_ ์์กด์ฑ์ ๊ฐ์ ธ์ผ์ง ์ปจํธ๋กค ์์กด์ฑ์ ๊ฐ์ ธ์ผ
ํ๋๊ฒ ์๋์ ์์๋์ญ์์ค. ๋ง์ฝ ๋๋ฒ์งธ ๋ก๋๋ฅผ ์ํ ์ฃผ์๊ฐ ์ฒซ๋ฒ์งธ ๋ก๋์
์์กด์ ์ด์ง๋ง ๊ทธ ์์กด์ฑ์ ์กฐ๊ฑด์ ์ด์ง ๊ทธ ์ฃผ์ ์์ฒด๋ฅผ ๊ฐ์ ธ์ค๋๊ฒ ์๋๋ผ๋ฉด,
๊ทธ๊ฒ์ _์ปจํธ๋กค_ ์์กด์ฑ์ด๊ณ , ์ด ๊ฒฝ์ฐ์๋ ์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด๋ ๊ทธ๋ณด๋ค ๊ฐ๋ ฅํ
๋ฌด์ธ๊ฐ๊ฐ ํ์ํฉ๋๋ค. ๋ ์์ธํ ๋ด์ฉ์ ์ํด์๋ "์ปจํธ๋กค ์์กด์ฑ" ์๋ธ์น์
์
์ฐธ๊ณ ํ์๊ธฐ ๋ฐ๋๋๋ค.
[!] ๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๋ ๋ณดํต ์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด๋ค๊ณผ ํจ๊ป ์ง์ ๋ง์ถฐ ์ฌ์ฉ๋์ด์ผ
ํฉ๋๋ค; "SMP ๋ฐฐ๋ฆฌ์ด ์ง๋ง์ถ๊ธฐ" ์๋ธ์น์
์ ์ฐธ๊ณ ํ์ธ์.
(3) ์ฝ๊ธฐ (๋๋ ๋ก๋) ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด.
์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด๋ ๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด ๊ธฐ๋ฅ์ ๋ณด์ฅ์ฌํญ์ ๋ํด์ ๋ฐฐ๋ฆฌ์ด๋ณด๋ค
์์ ๋ช
์๋ ๋ชจ๋ LOAD ์คํผ๋ ์ด์
๋ค์ด ๋ฐฐ๋ฆฌ์ด ๋ค์ ๋ช
์๋๋ ๋ชจ๋ LOAD
์คํผ๋ ์ด์
๋ค๋ณด๋ค ๋จผ์ ํํด์ง ๊ฒ์ผ๋ก ์์คํ
์ ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ค์ ๋ณด์ฌ์ง ๊ฒ์
๋ณด์ฅํฉ๋๋ค.
์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด๋ ๋ก๋ ์คํผ๋ ์ด์
์ ํํด์ง๋ ๋ถ๋ถ์ ์์ ์ธ์ฐ๊ธฐ์
๋๋ค; ์คํ ์ด
์คํผ๋ ์ด์
์ ๋ํด์๋ ์ด๋ค ์ํฅ๋ ๋ผ์น์ง ์์ต๋๋ค.
์ฝ๊ธฐ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ ๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๋ฅผ ๋ด์ฅํ๋ฏ๋ก ๋ฐ์ดํฐ ์์กด์ฑ
๋ฐฐ๋ฆฌ์ด๋ฅผ ๋์ ํ ์ ์์ต๋๋ค.
[!] ์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด๋ ์ผ๋ฐ์ ์ผ๋ก ์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด๋ค๊ณผ ํจ๊ป ์ง์ ๋ง์ถฐ ์ฌ์ฉ๋์ด์ผ
ํฉ๋๋ค; "SMP ๋ฐฐ๋ฆฌ์ด ์ง๋ง์ถ๊ธฐ" ์๋ธ์น์
์ ์ฐธ๊ณ ํ์ธ์.
(4) ๋ฒ์ฉ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด.
๋ฒ์ฉ(general) ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ ๋ฐฐ๋ฆฌ์ด๋ณด๋ค ์์ ๋ช
์๋ ๋ชจ๋ LOAD ์ STORE
์คํผ๋ ์ด์
๋ค์ด ๋ฐฐ๋ฆฌ์ด ๋ค์ ๋ช
์๋ ๋ชจ๋ LOAD ์ STORE ์คํผ๋ ์ด์
๋ค๋ณด๋ค
๋จผ์ ์ํ๋ ๊ฒ์ผ๋ก ์์คํ
์ ๋๋จธ์ง ์ปดํฌ๋ํธ๋ค์ ๋ณด์ด๊ฒ ๋จ์ ๋ณด์ฅํฉ๋๋ค.
๋ฒ์ฉ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ ๋ก๋์ ์คํ ์ด ๋ชจ๋์ ๋ํ ๋ถ๋ถ์ ์์ ์ธ์ฐ๊ธฐ์
๋๋ค.
๋ฒ์ฉ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ ์ฝ๊ธฐ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด, ์ฐ๊ธฐ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด ๋ชจ๋๋ฅผ
๋ด์ฅํ๋ฏ๋ก, ๋ ๋ฐฐ๋ฆฌ์ด๋ฅผ ๋ชจ๋ ๋์ ํ ์ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋๊ฐ์ ๋ช
์์ ์ด์ง ์์ ํ์
์ด ์์ต๋๋ค:
(5) ACQUIRE ์คํผ๋ ์ด์
.
์ด ํ์
์ ์คํผ๋ ์ด์
์ ๋จ๋ฐฉํฅ์ ํฌ๊ณผ์ฑ ๋ฐฐ๋ฆฌ์ด์ฒ๋ผ ๋์ํฉ๋๋ค. ACQUIRE
์คํผ๋ ์ด์
๋ค์ ๋ชจ๋ ๋ฉ๋ชจ๋ฆฌ ์คํผ๋ ์ด์
๋ค์ด ACQUIRE ์คํผ๋ ์ด์
ํ์
์ผ์ด๋ ๊ฒ์ผ๋ก ์์คํ
์ ๋๋จธ์ง ์ปดํฌ๋ํธ๋ค์ ๋ณด์ด๊ฒ ๋ ๊ฒ์ด ๋ณด์ฅ๋ฉ๋๋ค.
LOCK ์คํผ๋ ์ด์
๊ณผ smp_load_acquire(), smp_cond_acquire() ์คํผ๋ ์ด์
๋
ACQUIRE ์คํผ๋ ์ด์
์ ํฌํจ๋ฉ๋๋ค. smp_cond_acquire() ์คํผ๋ ์ด์
์ ์ปจํธ๋กค
์์กด์ฑ๊ณผ smp_rmb() ๋ฅผ ์ฌ์ฉํด์ ACQUIRE ์ ์๋ฏธ์ ์๊ตฌ์ฌํญ(semantic)์
์ถฉ์กฑ์ํต๋๋ค.
ACQUIRE ์คํผ๋ ์ด์
์์ ๋ฉ๋ชจ๋ฆฌ ์คํผ๋ ์ด์
๋ค์ ACQUIRE ์คํผ๋ ์ด์
์๋ฃ ํ์
์ํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ผ ์ ์์ต๋๋ค.
ACQUIRE ์คํผ๋ ์ด์
์ ๊ฑฐ์ ํญ์ RELEASE ์คํผ๋ ์ด์
๊ณผ ์ง์ ์ง์ด ์ฌ์ฉ๋์ด์ผ
ํฉ๋๋ค.
(6) RELEASE ์คํผ๋ ์ด์
.
์ด ํ์
์ ์คํผ๋ ์ด์
๋ค๋ ๋จ๋ฐฉํฅ ํฌ๊ณผ์ฑ ๋ฐฐ๋ฆฌ์ด์ฒ๋ผ ๋์ํฉ๋๋ค. RELEASE
์คํผ๋ ์ด์
์์ ๋ชจ๋ ๋ฉ๋ชจ๋ฆฌ ์คํผ๋ ์ด์
๋ค์ RELEASE ์คํผ๋ ์ด์
์ ์ ์๋ฃ๋
๊ฒ์ผ๋ก ์์คํ
์ ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ค์ ๋ณด์ฌ์ง ๊ฒ์ด ๋ณด์ฅ๋ฉ๋๋ค. UNLOCK ๋ฅ์
์คํผ๋ ์ด์
๋ค๊ณผ smp_store_release() ์คํผ๋ ์ด์
๋ RELEASE ์คํผ๋ ์ด์
์
์ผ์ข
์
๋๋ค.
RELEASE ์คํผ๋ ์ด์
๋ค์ ๋ฉ๋ชจ๋ฆฌ ์คํผ๋ ์ด์
๋ค์ RELEASE ์คํผ๋ ์ด์
์ด
์๋ฃ๋๊ธฐ ์ ์ ํํด์ง ๊ฒ์ฒ๋ผ ๋ณด์ผ ์ ์์ต๋๋ค.
ACQUIRE ์ RELEASE ์คํผ๋ ์ด์
์ ์ฌ์ฉ์ ์ผ๋ฐ์ ์ผ๋ก ๋ค๋ฅธ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด์
ํ์์ฑ์ ์์ฑ๋๋ค (ํ์ง๋ง "MMIO ์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด" ์๋ธ์น์
์์ ์ค๋ช
๋๋ ์์ธ๋ฅผ
์์๋์ธ์). ๋ํ, RELEASE+ACQUIRE ์กฐํฉ์ ๋ฒ์ฉ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด์ฒ๋ผ ๋์ํ
๊ฒ์ ๋ณด์ฅํ์ง -์์ต๋๋ค-. ํ์ง๋ง, ์ด๋ค ๋ณ์์ ๋ํ RELEASE ์คํผ๋ ์ด์
์
์์๋ ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค๋ค์ ์ํ ๊ฒฐ๊ณผ๋ ์ด RELEASE ์คํผ๋ ์ด์
์ ๋ค์ด์ด ๊ฐ์
๋ณ์์ ๋ํด ์ํ๋ ACQUIRE ์คํผ๋ ์ด์
์ ๋ค๋ฐ๋ฅด๋ ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค์๋ ๋ณด์ฌ์ง
๊ฒ์ด ๋ณด์ฅ๋ฉ๋๋ค. ๋ค๋ฅด๊ฒ ๋งํ์๋ฉด, ์ฃผ์ด์ง ๋ณ์์ ํฌ๋ฆฌํฐ์ปฌ ์น์
์์๋, ํด๋น
๋ณ์์ ๋ํ ์์ ํฌ๋ฆฌํฐ์ปฌ ์น์
์์์ ๋ชจ๋ ์ก์ธ์ค๋ค์ด ์๋ฃ๋์์ ๊ฒ์
๋ณด์ฅํฉ๋๋ค.
์ฆ, ACQUIRE ๋ ์ต์ํ์ "์ทจ๋" ๋์์ฒ๋ผ, ๊ทธ๋ฆฌ๊ณ RELEASE ๋ ์ต์ํ์ "๊ณต๊ฐ"
์ฒ๋ผ ๋์ํ๋ค๋ ์๋ฏธ์
๋๋ค.
atomic_ops.txt ์์ ์ค๋ช
๋๋ ์ดํ ๋ฏน ์คํผ๋ ์ด์
๋ค ์ค์๋ ์์ ํ ์์์กํ ๊ฒ๋ค๊ณผ
(๋ฐฐ๋ฆฌ์ด๋ฅผ ์ฌ์ฉํ์ง ์๋) ์ํ๋ ์์์ ๊ฒ๋ค ์ธ์ ACQUIRE ์ RELEASE ๋ถ๋ฅ์
๊ฒ๋ค๋ ์กด์ฌํฉ๋๋ค. ๋ก๋์ ์คํ ์ด๋ฅผ ๋ชจ๋ ์ํํ๋ ์กฐํฉ๋ ์ดํ ๋ฏน ์คํผ๋ ์ด์
์์,
ACQUIRE ๋ ํด๋น ์คํผ๋ ์ด์
์ ๋ก๋ ๋ถ๋ถ์๋ง ์ ์ฉ๋๊ณ RELEASE ๋ ํด๋น
์คํผ๋ ์ด์
์ ์คํ ์ด ๋ถ๋ถ์๋ง ์ ์ฉ๋ฉ๋๋ค.
๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ค์ ๋ CPU ๊ฐ, ๋๋ CPU ์ ๋๋ฐ์ด์ค ๊ฐ์ ์ํธ์์ฉ์ ๊ฐ๋ฅ์ฑ์ด ์์
๋์๋ง ํ์ํฉ๋๋ค. ๋ง์ฝ ์ด๋ค ์ฝ๋์ ๊ทธ๋ฐ ์ํธ์์ฉ์ด ์์ ๊ฒ์ด ๋ณด์ฅ๋๋ค๋ฉด, ํด๋น
์ฝ๋์์๋ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ ์ฌ์ฉํ ํ์๊ฐ ์์ต๋๋ค.
์ด๊ฒ๋ค์ _์ต์ํ์_ ๋ณด์ฅ์ฌํญ๋ค์์ ์์๋์ธ์. ๋ค๋ฅธ ์ํคํ
์ณ์์๋ ๋ ๊ฐ๋ ฅํ
๋ณด์ฅ์ฌํญ์ ์ ๊ณตํ ์๋ ์์ต๋๋ค๋ง, ๊ทธ๋ฐ ๋ณด์ฅ์ฌํญ์ ์ํคํ
์ณ ์ข
์์ ์ฝ๋ ์ด์ธ์
๋ถ๋ถ์์๋ ์ ๋ขฐ๋์ง _์์_ ๊ฒ๋๋ค.
๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด์ ๋ํด ๊ฐ์ ํด์ ์๋ ๊ฒ
-------------------------------------
๋ฆฌ๋
์ค ์ปค๋ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ค์ด ๋ณด์ฅํ์ง ์๋ ๊ฒ๋ค์ด ์์ต๋๋ค:
(*) ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด ์์์ ๋ช
์๋ ์ด๋ค ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค๋ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด ๋ช
๋ น์ ์ํ
์๋ฃ ์์ ๊น์ง _์๋ฃ_ ๋ ๊ฒ์ด๋ ๋ณด์ฅ์ ์์ต๋๋ค; ๋ฐฐ๋ฆฌ์ด๊ฐ ํ๋ ์ผ์ CPU ์
์ก์ธ์ค ํ์ ํน์ ํ์
์ ์ก์ธ์ค๋ค์ ๋์ ์ ์๋ ์ ์ ๊ธ๋ ๊ฒ์ผ๋ก ์๊ฐ๋ ์
์์ต๋๋ค.
(*) ํ CPU ์์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ ์ํํ๋๊ฒ ์์คํ
์ ๋ค๋ฅธ CPU ๋ ํ๋์จ์ด์
์ด๋ค ์ง์ ์ ์ธ ์ํฅ์ ๋ผ์น๋ค๋ ๋ณด์ฅ์ ์กด์ฌํ์ง ์์ต๋๋ค. ๋ฐฐ๋ฆฌ์ด ์ํ์ด
๋ง๋๋ ๊ฐ์ ์ ์ํฅ์ ๋๋ฒ์งธ CPU ๊ฐ ์ฒซ๋ฒ์งธ CPU ์ ์ก์ธ์ค๋ค์ ๊ฒฐ๊ณผ๋ฅผ
๋ฐ๋ผ๋ณด๋ ์์๊ฐ ๋ฉ๋๋ค๋ง, ๋ค์ ํญ๋ชฉ์ ๋ณด์ธ์:
(*) ์ฒซ๋ฒ์งธ CPU ๊ฐ ๋๋ฒ์งธ CPU ์ ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค๋ค์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ๋ผ๋ณผ ๋, _์ค๋ น_
๋๋ฒ์งธ CPU ๊ฐ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ ์ฌ์ฉํ๋ค ํด๋, ์ฒซ๋ฒ์งธ CPU _๋ํ_ ๊ทธ์ ๋ง๋
๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ ์ฌ์ฉํ์ง ์๋๋ค๋ฉด ("SMP ๋ฐฐ๋ฆฌ์ด ์ง๋ง์ถ๊ธฐ" ์๋ธ์น์
์
์ฐธ๊ณ ํ์ธ์) ๊ทธ ๊ฒฐ๊ณผ๊ฐ ์ฌ๋ฐ๋ฅธ ์์๋ก ๋ณด์ฌ์ง๋ค๋ ๋ณด์ฅ์ ์์ต๋๋ค.
(*) CPU ๋ฐ๊นฅ์ ํ๋์จ์ด[*] ๊ฐ ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค๋ค์ ์์๋ฅผ ๋ฐ๊พธ์ง ์๋๋ค๋ ๋ณด์ฅ์
์กด์ฌํ์ง ์์ต๋๋ค. CPU ์บ์ ์ผ๊ด์ฑ ๋ฉ์ปค๋์ฆ์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด์ ๊ฐ์ ์
์ํฅ์ CPU ์ฌ์ด์ ์ ํํ๊ธด ํ์ง๋ง, ์์๋๋ก ์ ํํ์ง๋ ์์ ์ ์์ต๋๋ค.
[*] ๋ฒ์ค ๋ง์คํฐ๋ง DMA ์ ์ผ๊ด์ฑ์ ๋ํด์๋ ๋ค์์ ์ฐธ๊ณ ํ์๊ธฐ ๋ฐ๋๋๋ค:
Documentation/PCI/pci.txt
Documentation/DMA-API-HOWTO.txt
Documentation/DMA-API.txt
๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด
--------------------
๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด์ ์ฌ์ฉ์ ์์ด ์ง์ผ์ผ ํ๋ ์ฌํญ๋ค์ ์ฝ๊ฐ ๋ฏธ๋ฌํ๊ณ , ๋ฐ์ดํฐ
์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๊ฐ ์ฌ์ฉ๋์ด์ผ ํ๋ ์ํฉ๋ ํญ์ ๋ช
๋ฐฑํ์ง๋ ์์ต๋๋ค. ์ค๋ช
์ ์ํด
๋ค์์ ์ด๋ฒคํธ ์ํ์ค๋ฅผ ์๊ฐํด ๋ด
์๋ค:
CPU 1 CPU 2
=============== ===============
{ A == 1, B == 2, C == 3, P == &A, Q == &C }
B = 4;
<์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด>
WRITE_ONCE(P, &B)
Q = READ_ONCE(P);
D = *Q;
์ฌ๊ธฐ์ ๋ถ๋ช
ํ ๋ฐ์ดํฐ ์์กด์ฑ์ด ์กด์ฌํ๋ฏ๋ก, ์ด ์ํ์ค๊ฐ ๋๋ฌ์ ๋ Q ๋ &A ๋๋ &B
์ผ ๊ฒ์ด๊ณ , ๋ฐ๋ผ์:
(Q == &A) ๋ (D == 1) ๋ฅผ,
(Q == &B) ๋ (D == 4) ๋ฅผ ์๋ฏธํฉ๋๋ค.
ํ์ง๋ง! CPU 2 ๋ B ์ ์
๋ฐ์ดํธ๋ฅผ ์ธ์ํ๊ธฐ ์ ์ P ์ ์
๋ฐ์ดํธ๋ฅผ ์ธ์ํ ์ ์๊ณ ,
๋ฐ๋ผ์ ๋ค์์ ๊ฒฐ๊ณผ๊ฐ ๊ฐ๋ฅํฉ๋๋ค:
(Q == &B) and (D == 2) ????
์ด๋ฐ ๊ฒฐ๊ณผ๋ ์ผ๊ด์ฑ์ด๋ ์ธ๊ณผ ๊ด๊ณ ์ ์ง๊ฐ ์คํจํ ๊ฒ์ฒ๋ผ ๋ณด์ผ ์๋ ์๊ฒ ์ง๋ง,
๊ทธ๋ ์ง ์์ต๋๋ค, ๊ทธ๋ฆฌ๊ณ ์ด ํ์์ (DEC Alpha ์ ๊ฐ์) ์ฌ๋ฌ CPU ์์ ์ค์ ๋ก
๋ฐ๊ฒฌ๋ ์ ์์ต๋๋ค.
์ด ๋ฌธ์ ์ํฉ์ ์ ๋๋ก ํด๊ฒฐํ๊ธฐ ์ํด, ๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๋ ๊ทธ๋ณด๋ค ๊ฐํ๋
๋ฌด์ธ๊ฐ๊ฐ ์ฃผ์๋ฅผ ์ฝ์ด์ฌ ๋์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด์ฌ ๋ ์ฌ์ด์ ์ถ๊ฐ๋์ด์ผ๋ง ํฉ๋๋ค:
CPU 1 CPU 2
=============== ===============
{ A == 1, B == 2, C == 3, P == &A, Q == &C }
B = 4;
<์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด>
WRITE_ONCE(P, &B);
Q = READ_ONCE(P);
<๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด>
D = *Q;
์ด ๋ณ๊ฒฝ์ ์์ ์ฒ์ ๋๊ฐ์ง ๊ฒฐ๊ณผ ์ค ํ๋๋ง์ด ๋ฐ์ํ ์ ์๊ณ , ์ธ๋ฒ์งธ์ ๊ฒฐ๊ณผ๋
๋ฐ์ํ ์ ์๋๋ก ํฉ๋๋ค.
๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๋ ์์กด์ ์ฐ๊ธฐ์ ๋ํด์๋ ์์๋ฅผ ์ก์์ค๋๋ค:
CPU 1 CPU 2
=============== ===============
{ A == 1, B == 2, C = 3, P == &A, Q == &C }
B = 4;
<์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด>
WRITE_ONCE(P, &B);
Q = READ_ONCE(P);
<๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด>
*Q = 5;
์ด ๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๋ Q ๋ก์ ์ฝ๊ธฐ๊ฐ *Q ๋ก์ ์คํ ์ด์ ์์๋ฅผ ๋ง์ถ๊ฒ
ํด์ค๋๋ค. ์ด๋ ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋ง์ต๋๋ค:
(Q == &B) && (B == 4)
์ด๋ฐ ํจํด์ ๋๋ฌผ๊ฒ ์ฌ์ฉ๋์ด์ผ ํจ์ ์์ ๋์๊ธฐ ๋ฐ๋๋๋ค. ๋ฌด์๋ณด๋ค๋, ์์กด์ฑ
์์ ๊ท์น์ ์๋๋ ์ฐ๊ธฐ ์์
์ -์๋ฐฉ- ํด์ ๊ทธ๋ก ์ธํด ๋ฐ์ํ๋ ๋น์ผ ์บ์ ๋ฏธ์ค๋
์์ ๋ ค๋ ๊ฒ์
๋๋ค. ์ด ํจํด์ ๋๋ฌผ๊ฒ ๋ฐ์ํ๋ ์๋ฌ ์กฐ๊ฑด ๊ฐ์๊ฒ๋ค์ ๊ธฐ๋กํ๋๋ฐ
์ฌ์ฉ๋ ์ ์๊ณ , ์ด๋ ๊ฒ ๋ฐฐ๋ฆฌ์ด๋ฅผ ์ฌ์ฉํด ์์๋ฅผ ์งํค๊ฒ ํจ์ผ๋ก์จ ๊ทธ๋ฐ ๊ธฐ๋ก์ด
์ฌ๋ผ์ง๋ ๊ฒ์ ๋ง์ต๋๋ค.
[!] ์๋นํ ๋น์ง๊ด์ ์ธ ์ด ์ํฉ์ ๋ถ๋ฆฌ๋ ์บ์๋ฅผ ๊ฐ์ง ๊ธฐ๊ณ, ์๋ฅผ ๋ค์ด ํ ์บ์
๋ฑ
ํฌ๊ฐ ์ง์๋ฒ ์บ์ ๋ผ์ธ์ ์ฒ๋ฆฌํ๊ณ ๋ค๋ฅธ ๋ฑ
ํฌ๋ ํ์๋ฒ ์บ์ ๋ผ์ธ์ ์ฒ๋ฆฌํ๋ ๊ธฐ๊ณ
๋ฑ์์ ๊ฐ์ฅ ์ ๋ฐ์ํฉ๋๋ค. ํฌ์ธํฐ P ๋ ํ์ ๋ฒํธ์ ์บ์ ๋ผ์ธ์ ์๊ณ , ๋ณ์ B ๋
์ง์ ๋ฒํธ ์บ์ ๋ผ์ธ์ ์๋ค๊ณ ์๊ฐํด ๋ด
์๋ค. ๊ทธ๋ฐ ์ํ์์ ์ฝ๊ธฐ ์์
์ ํ๋ CPU
์ ์ง์๋ฒ ๋ฑ
ํฌ๋ ํ ์ผ์ด ์์ฌ ๋งค์ฐ ๋ฐ์์ง๋ง ํ์๋ฒ ๋ฑ
ํฌ๋ ํ ์ผ์ด ์์ด ์๋ฌด
์ผ๋ ํ์ง ์๊ณ ์์๋ค๋ฉด, ํฌ์ธํฐ P ๋ ์ ๊ฐ (&B) ์, ๊ทธ๋ฆฌ๊ณ ๋ณ์ B ๋ ์๋ ๊ฐ
(2) ์ ๊ฐ์ง๊ณ ์๋ ์ํ๊ฐ ๋ณด์ฌ์ง ์๋ ์์ต๋๋ค.
๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๋ ๋งค์ฐ ์ค์ํ๋ฐ, ์๋ฅผ ๋ค์ด RCU ์์คํ
์์ ๊ทธ๋ ์ต๋๋ค.
include/linux/rcupdate.h ์ rcu_assign_pointer() ์ rcu_dereference() ๋ฅผ
์ฐธ๊ณ ํ์ธ์. ์ฌ๊ธฐ์ ๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๋ RCU ๋ก ๊ด๋ฆฌ๋๋ ํฌ์ธํฐ์ ํ๊ฒ์ ํ์ฌ
ํ๊ฒ์์ ์์ ๋ ์๋ก์ด ํ๊ฒ์ผ๋ก ๋ฐ๊พธ๋ ์์
์์ ์๋ก ์์ ๋ ํ๊ฒ์ด ์ด๊ธฐํ๊ฐ
์๋ฃ๋์ง ์์ ์ฑ๋ก ๋ณด์ฌ์ง๋ ์ผ์ด ์ผ์ด๋์ง ์๊ฒ ํด์ค๋๋ค.
๋ ๋ง์ ์๋ฅผ ์ํด์ "์บ์ ์ผ๊ด์ฑ" ์๋ธ์น์
์ ์ฐธ๊ณ ํ์ธ์.
์ปจํธ๋กค ์์กด์ฑ
-------------
๋ก๋-๋ก๋ ์ปจํธ๋กค ์์กด์ฑ์ ๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๋ง์ผ๋ก๋ ์ ํํ ๋์ํ ์๊ฐ
์์ด์ ์ฝ๊ธฐ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ ํ์๋ก ํฉ๋๋ค. ์๋์ ์ฝ๋๋ฅผ ๋ด
์๋ค:
q = READ_ONCE(a);
if (q) {
<๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด> /* BUG: No data dependency!!! */
p = READ_ONCE(b);
}
์ด ์ฝ๋๋ ์ํ๋ ๋๋ก์ ํจ๊ณผ๋ฅผ ๋ด์ง ๋ชปํ ์ ์๋๋ฐ, ์ด ์ฝ๋์๋ ๋ฐ์ดํฐ ์์กด์ฑ์ด
์๋๋ผ ์ปจํธ๋กค ์์กด์ฑ์ด ์กด์ฌํ๊ธฐ ๋๋ฌธ์ผ๋ก, ์ด๋ฐ ์ํฉ์์ CPU ๋ ์คํ ์๋๋ฅผ ๋
๋น ๋ฅด๊ฒ ํ๊ธฐ ์ํด ๋ถ๊ธฐ ์กฐ๊ฑด์ ๊ฒฐ๊ณผ๋ฅผ ์์ธกํ๊ณ ์ฝ๋๋ฅผ ์ฌ๋ฐฐ์น ํ ์ ์์ด์ ๋ค๋ฅธ
CPU ๋ b ๋ก๋ถํฐ์ ๋ก๋ ์คํผ๋ ์ด์
์ด a ๋ก๋ถํฐ์ ๋ก๋ ์คํผ๋ ์ด์
๋ณด๋ค ๋จผ์ ๋ฐ์ํ
๊ฑธ๋ก ์ธ์ํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์ ์ ๋ง๋ก ํ์ํ๋ ๊ฑด ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
q = READ_ONCE(a);
if (q) {
<์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด>
p = READ_ONCE(b);
}
ํ์ง๋ง, ์คํ ์ด ์คํผ๋ ์ด์
์ ์์ธก์ ์ผ๋ก ์ํ๋์ง ์์ต๋๋ค. ์ฆ, ๋ค์ ์์์์
๊ฐ์ด ๋ก๋-์คํ ์ด ์ปจํธ๋กค ์์กด์ฑ์ด ์กด์ฌํ๋ ๊ฒฝ์ฐ์๋ ์์๊ฐ -์ง์ผ์ง๋ค-๋
์๋ฏธ์
๋๋ค.
q = READ_ONCE(a);
if (q) {
WRITE_ONCE(b, p);
}
์ปจํธ๋กค ์์กด์ฑ์ ๋ณดํต ๋ค๋ฅธ ํ์
์ ๋ฐฐ๋ฆฌ์ด๋ค๊ณผ ์ง์ ๋ง์ถฐ ์ฌ์ฉ๋ฉ๋๋ค. ๊ทธ๋ ๋ค๊ณค
ํ๋, READ_ONCE() ๋ ๋ฐ๋์ ์ฌ์ฉํด์ผ ํจ์ ๋ถ๋ ๋ช
์ฌํ์ธ์! READ_ONCE() ๊ฐ
์๋ค๋ฉด, ์ปดํ์ผ๋ฌ๊ฐ 'a' ๋ก๋ถํฐ์ ๋ก๋๋ฅผ 'a' ๋ก๋ถํฐ์ ๋๋ค๋ฅธ ๋ก๋์, 'b' ๋ก์
์คํ ์ด๋ฅผ 'b' ๋ก์ ๋๋ค๋ฅธ ์คํ ์ด์ ์กฐํฉํด ๋ฒ๋ ค ๋งค์ฐ ๋น์ง๊ด์ ์ธ ๊ฒฐ๊ณผ๋ฅผ ์ด๋ํ ์
์์ต๋๋ค.
์ด๊ฑธ๋ก ๋์ด ์๋๊ฒ, ์ปดํ์ผ๋ฌ๊ฐ ๋ณ์ 'a' ์ ๊ฐ์ด ํญ์ 0์ด ์๋๋ผ๊ณ ์ฆ๋ช
ํ ์
์๋ค๋ฉด, ์์ ์์์ "if" ๋ฌธ์ ์์ ์ ๋ค์๊ณผ ๊ฐ์ด ์ต์ ํ ํ ์๋ ์์ต๋๋ค:
q = a;
b = p; /* BUG: Compiler and CPU can both reorder!!! */
๊ทธ๋ฌ๋ READ_ONCE() ๋ฅผ ๋ฐ๋์ ์ฌ์ฉํ์ธ์.
๋ค์๊ณผ ๊ฐ์ด "if" ๋ฌธ์ ์๊ฐ๋ ๋ธ๋์น์ ๋ชจ๋ ์กด์ฌํ๋ ๋์ผํ ์คํ ์ด์ ๋ํด ์์๋ฅผ
๊ฐ์ ํ๊ณ ์ถ์ ๊ฒฝ์ฐ๊ฐ ์์ ์ ์์ต๋๋ค:
q = READ_ONCE(a);
if (q) {
barrier();
WRITE_ONCE(b, p);
do_something();
} else {
barrier();
WRITE_ONCE(b, p);
do_something_else();
}
์ํ๊น๊ฒ๋, ํ์ฌ์ ์ปดํ์ผ๋ฌ๋ค์ ๋์ ์ต์ ํ ๋ ๋ฒจ์์๋ ์ด๊ฑธ ๋ค์๊ณผ ๊ฐ์ด
๋ฐ๊ฟ๋ฒ๋ฆฝ๋๋ค:
q = READ_ONCE(a);
barrier();
WRITE_ONCE(b, p); /* BUG: No ordering vs. load from a!!! */
if (q) {
/* WRITE_ONCE(b, p); -- moved up, BUG!!! */
do_something();
} else {
/* WRITE_ONCE(b, p); -- moved up, BUG!!! */
do_something_else();
}
์ด์ 'a' ์์์ ๋ก๋์ 'b' ๋ก์ ์คํ ์ด ์ฌ์ด์๋ ์กฐ๊ฑด์ ๊ด๊ณ๊ฐ ์๊ธฐ ๋๋ฌธ์ CPU
๋ ์ด๋ค์ ์์๋ฅผ ๋ฐ๊ฟ ์ ์๊ฒ ๋ฉ๋๋ค: ์ด๋ฐ ๊ฒฝ์ฐ์ ์กฐ๊ฑด์ ๊ด๊ณ๋ ๋ฐ๋์
ํ์ํ๋ฐ, ๋ชจ๋ ์ปดํ์ผ๋ฌ ์ต์ ํ๊ฐ ์ด๋ฃจ์ด์ง๊ณ ๋ ํ์ ์ด์
๋ธ๋ฆฌ ์ฝ๋์์๋
๋ง์ฐฌ๊ฐ์ง์
๋๋ค. ๋ฐ๋ผ์, ์ด ์์์ ์์๋ฅผ ์งํค๊ธฐ ์ํด์๋ smp_store_release()
์ ๊ฐ์ ๋ช
์์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๊ฐ ํ์ํฉ๋๋ค:
q = READ_ONCE(a);
if (q) {
smp_store_release(&b, p);
do_something();
} else {
smp_store_release(&b, p);
do_something_else();
}
๋ฐ๋ฉด์ ๋ช
์์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๊ฐ ์๋ค๋ฉด, ์ด๋ฐ ๊ฒฝ์ฐ์ ์์๋ ์คํ ์ด ์คํผ๋ ์ด์
๋ค์ด
์๋ก ๋ค๋ฅผ ๋์๋ง ๋ณด์ฅ๋๋๋ฐ, ์๋ฅผ ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ์ฐ์
๋๋ค:
q = READ_ONCE(a);
if (q) {
WRITE_ONCE(b, p);
do_something();
} else {
WRITE_ONCE(b, r);
do_something_else();
}
์ฒ์์ READ_ONCE() ๋ ์ปดํ์ผ๋ฌ๊ฐ 'a' ์ ๊ฐ์ ์ฆ๋ช
ํด๋ด๋ ๊ฒ์ ๋ง๊ธฐ ์ํด ์ฌ์ ํ
ํ์ํฉ๋๋ค.
๋ํ, ๋ก์ปฌ ๋ณ์ 'q' ๋ฅผ ๊ฐ์ง๊ณ ํ๋ ์ผ์ ๋ํด ์ฃผ์ํด์ผ ํ๋๋ฐ, ๊ทธ๋ฌ์ง ์์ผ๋ฉด
์ปดํ์ผ๋ฌ๋ ๊ทธ ๊ฐ์ ์ถ์ธกํ๊ณ ๋๋ค์ ํ์ํ ์กฐ๊ฑด๊ด๊ณ๋ฅผ ์์ ๋ฒ๋ฆด ์ ์์ต๋๋ค.
์๋ฅผ ๋ค๋ฉด:
q = READ_ONCE(a);
if (q % MAX) {
WRITE_ONCE(b, p);
do_something();
} else {
WRITE_ONCE(b, r);
do_something_else();
}
๋ง์ฝ MAX ๊ฐ 1 ๋ก ์ ์๋ ์์๋ผ๋ฉด, ์ปดํ์ผ๋ฌ๋ (q % MAX) ๋ 0์ด๋ ๊ฒ์ ์์์ฑ๊ณ ,
์์ ์ฝ๋๋ฅผ ์๋์ ๊ฐ์ด ๋ฐ๊ฟ๋ฒ๋ฆด ์ ์์ต๋๋ค:
q = READ_ONCE(a);
WRITE_ONCE(b, p);
do_something_else();
์ด๋ ๊ฒ ๋๋ฉด, CPU ๋ ๋ณ์ 'a' ๋ก๋ถํฐ์ ๋ก๋์ ๋ณ์ 'b' ๋ก์ ์คํ ์ด ์ฌ์ด์ ์์๋ฅผ
์ง์ผ์ค ํ์๊ฐ ์์ด์ง๋๋ค. barrier() ๋ฅผ ์ถ๊ฐํด ํด๊ฒฐํด ๋ณด๊ณ ์ถ๊ฒ ์ง๋ง, ๊ทธ๊ฑด
๋์์ด ์๋ฉ๋๋ค. ์กฐ๊ฑด ๊ด๊ณ๋ ์ฌ๋ผ์ก๊ณ , barrier() ๋ ์ด๋ฅผ ๋๋๋ฆฌ์ง ๋ชปํฉ๋๋ค.
๋ฐ๋ผ์, ์ด ์์๋ฅผ ์ง์ผ์ผ ํ๋ค๋ฉด, MAX ๊ฐ 1 ๋ณด๋ค ํฌ๋ค๋ ๊ฒ์, ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ๋ฒ์
์ฌ์ฉํด ๋ถ๋ช
ํ ํด์ผ ํฉ๋๋ค:
q = READ_ONCE(a);
BUILD_BUG_ON(MAX <= 1); /* Order load from a with store to b. */
if (q % MAX) {
WRITE_ONCE(b, p);
do_something();
} else {
WRITE_ONCE(b, r);
do_something_else();
}
'b' ๋ก์ ์คํ ์ด๋ค์ ์ฌ์ ํ ์๋ก ๋ค๋ฆ์ ์์๋์ธ์. ๋ง์ฝ ๊ทธ๊ฒ๋ค์ด ๋์ผํ๋ฉด,
์์์ ์ด์ผ๊ธฐํ๋ฏ, ์ปดํ์ผ๋ฌ๊ฐ ๊ทธ ์คํ ์ด ์คํผ๋ ์ด์
๋ค์ 'if' ๋ฌธ ๋ฐ๊นฅ์ผ๋ก
๋์ง์ด๋ผ ์ ์์ต๋๋ค.
๋ํ ์ด์ง ์กฐ๊ฑด๋ฌธ ํ๊ฐ์ ๋๋ฌด ์์กดํ์ง ์๋๋ก ์กฐ์ฌํด์ผ ํฉ๋๋ค. ๋ค์์ ์๋ฅผ
๋ด
์๋ค:
q = READ_ONCE(a);
if (q || 1 > 0)
WRITE_ONCE(b, 1);
์ฒซ๋ฒ์งธ ์กฐ๊ฑด๋ง์ผ๋ก๋ ๋ธ๋์น ์กฐ๊ฑด ์ ์ฒด๋ฅผ ๊ฑฐ์ง์ผ๋ก ๋ง๋ค ์ ์๊ณ ๋๋ฒ์งธ ์กฐ๊ฑด์ ํญ์
์ฐธ์ด๊ธฐ ๋๋ฌธ์, ์ปดํ์ผ๋ฌ๋ ์ด ์๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ๋ฐ๊ฟ์ ์ปจํธ๋กค ์์กด์ฑ์ ์์ ๋ฒ๋ฆด
์ ์์ต๋๋ค:
q = READ_ONCE(a);
WRITE_ONCE(b, 1);
์ด ์๋ ์ปดํ์ผ๋ฌ๊ฐ ์ฝ๋๋ฅผ ์ถ์ธก์ผ๋ก ์์ ํ ์ ์๋๋ก ๋ถ๋ช
ํ ํด์ผ ํ๋ค๋ ์ ์
๊ฐ์กฐํฉ๋๋ค. ์กฐ๊ธ ๋ ์ผ๋ฐ์ ์ผ๋ก ๋งํด์, READ_ONCE() ๋ ์ปดํ์ผ๋ฌ์๊ฒ ์ฃผ์ด์ง ๋ก๋
์คํผ๋ ์ด์
์ ์ํ ์ฝ๋๋ฅผ ์ ๋ง๋ก ๋ง๋ค๋๋ก ํ์ง๋ง, ์ปดํ์ผ๋ฌ๊ฐ ๊ทธ๋ ๊ฒ ๋ง๋ค์ด์ง
์ฝ๋์ ์ํ ๊ฒฐ๊ณผ๋ฅผ ์ฌ์ฉํ๋๋ก ๊ฐ์ ํ์ง๋ ์์ต๋๋ค.
๋ง์ง๋ง์ผ๋ก, ์ปจํธ๋กค ์์กด์ฑ์ ์ดํ์ฑ (transitivity) ์ ์ ๊ณตํ์ง -์์ต๋๋ค-. ์ด๊ฑด
x ์ y ๊ฐ ๋ ๋ค 0 ์ด๋ผ๋ ์ด๊ธฐ๊ฐ์ ๊ฐ์ก๋ค๋ ๊ฐ์ ํ์ ๋๊ฐ์ ์์ ๋ก
๋ณด์ด๊ฒ ์ต๋๋ค:
CPU 0 CPU 1
======================= =======================
r1 = READ_ONCE(x); r2 = READ_ONCE(y);
if (r1 > 0) if (r2 > 0)
WRITE_ONCE(y, 1); WRITE_ONCE(x, 1);
assert(!(r1 == 1 && r2 == 1));
์ด ๋ CPU ์์ ์์ assert() ์ ์กฐ๊ฑด์ ํญ์ ์ฐธ์ผ ๊ฒ์
๋๋ค. ๊ทธ๋ฆฌ๊ณ , ๋ง์ฝ ์ปจํธ๋กค
์์กด์ฑ์ด ์ดํ์ฑ์ (์ค์ ๋ก๋ ๊ทธ๋ฌ์ง ์์ง๋ง) ๋ณด์ฅํ๋ค๋ฉด, ๋ค์์ CPU ๊ฐ ์ถ๊ฐ๋์ด๋
์๋์ assert() ์กฐ๊ฑด์ ์ฐธ์ด ๋ ๊ฒ์
๋๋ค:
CPU 2
=====================
WRITE_ONCE(x, 2);
assert(!(r1 == 2 && r2 == 1 && x == 2)); /* FAILS!!! */
ํ์ง๋ง ์ปจํธ๋กค ์์กด์ฑ์ ์ดํ์ฑ์ ์ ๊ณตํ์ง -์๊ธฐ- ๋๋ฌธ์, ์ธ๊ฐ์ CPU ์์ ๊ฐ ์คํ
์๋ฃ๋ ํ์ ์์ assert() ์ ์กฐ๊ฑด์ ๊ฑฐ์ง์ผ๋ก ํ๊ฐ๋ ์ ์์ต๋๋ค. ์ธ๊ฐ์ CPU
์์ ๊ฐ ์์๋ฅผ ์งํค๊ธธ ์ํ๋ค๋ฉด, CPU 0 ์ CPU 1 ์ฝ๋์ ๋ก๋์ ์คํ ์ด ์ฌ์ด, "if"
๋ฌธ ๋ฐ๋ก ๋ค์์ smp_mb()๋ฅผ ๋ฃ์ด์ผ ํฉ๋๋ค. ๋ ๋์๊ฐ์, ์ต์ด์ ๋ CPU ์์ ๋
๋งค์ฐ ์ํํ๋ฏ๋ก ์ฌ์ฉ๋์ง ์์์ผ ํฉ๋๋ค.
์ด ๋๊ฐ์ ์์ ๋ ๋ค์ ๋
ผ๋ฌธ:
http://www.cl.cam.ac.uk/users/pes20/ppc-supplemental/test6.pdf ์
์ด ์ฌ์ดํธ: https://www.cl.cam.ac.uk/~pes20/ppcmem/index.html ์ ๋์จ LB ์ WWC
๋ฆฌํธ๋จธ์ค ํ
์คํธ์
๋๋ค.
์์ฝํ์๋ฉด:
(*) ์ปจํธ๋กค ์์กด์ฑ์ ์์ ๋ก๋๋ค์ ๋ค์ ์คํ ์ด๋ค์ ๋ํด ์์๋ฅผ ๋ง์ถฐ์ค๋๋ค.
ํ์ง๋ง, ๊ทธ ์ธ์ ์ด๋ค ์์๋ ๋ณด์ฅํ์ง -์์ต๋๋ค-: ์์ ๋ก๋์ ๋ค์ ๋ก๋๋ค
์ฌ์ด์๋, ์์ ์คํ ์ด์ ๋ค์ ์คํ ์ด๋ค ์ฌ์ด์๋์. ์ด๋ฐ ๋ค๋ฅธ ํํ์
์์๊ฐ ํ์ํ๋ค๋ฉด smp_rmb() ๋ smp_wmb()๋ฅผ, ๋๋, ์์ ์คํ ์ด๋ค๊ณผ ๋ค์
๋ก๋๋ค ์ฌ์ด์ ์์๋ฅผ ์ํด์๋ smp_mb() ๋ฅผ ์ฌ์ฉํ์ธ์.
(*) "if" ๋ฌธ์ ์๊ฐ๋ ๋ธ๋์น๊ฐ ๊ฐ์ ๋ณ์์์ ๋์ผํ ์คํ ์ด๋ก ์์ํ๋ค๋ฉด, ๊ทธ
์คํ ์ด๋ค์ ๊ฐ ์คํ ์ด ์์ smp_mb() ๋ฅผ ๋ฃ๊ฑฐ๋ smp_store_release() ๋ฅผ
์ฌ์ฉํด์ ์คํ ์ด๋ฅผ ํ๋ ์์ผ๋ก ์์๋ฅผ ๋ง์ถฐ์ค์ผ ํฉ๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ
์ํด "if" ๋ฌธ์ ์๊ฐ๋ ๋ธ๋์น์ ์์ ์ง์ ์ barrier() ๋ฅผ ๋ฃ๋ ๊ฒ๋ง์ผ๋ก๋
์ถฉ๋ถํ ํด๊ฒฐ์ด ๋์ง ์๋๋ฐ, ์ด๋ ์์ ์์์ ๋ณธ๊ฒ๊ณผ ๊ฐ์ด, ์ปดํ์ผ๋ฌ์
์ต์ ํ๋ barrier() ๊ฐ ์๋ฏธํ๋ ๋ฐ๋ฅผ ์งํค๋ฉด์๋ ์ปจํธ๋กค ์์กด์ฑ์ ์์์ํฌ
์ ์๊ธฐ ๋๋ฌธ์ด๋ผ๋ ์ ์ ๋ถ๋ ์์๋์๊ธฐ ๋ฐ๋๋๋ค.
(*) ์ปจํธ๋กค ์์กด์ฑ์ ์์ ๋ก๋์ ๋ค์ ์คํ ์ด ์ฌ์ด์ ์ต์ ํ๋์, ์คํ
์์ ์์์ ์กฐ๊ฑด๊ด๊ณ๋ฅผ ํ์๋ก ํ๋ฉฐ, ์ด ์กฐ๊ฑด๊ด๊ณ๋ ์์ ๋ก๋์ ๊ด๊ณ๋์ด์ผ
ํฉ๋๋ค. ๋ง์ฝ ์ปดํ์ผ๋ฌ๊ฐ ์กฐ๊ฑด ๊ด๊ณ๋ฅผ ์ต์ ํ๋ก ์์จ์ ์๋ค๋ฉด, ์์๋
์ต์ ํ๋ก ์์ ๋ฒ๋ ธ์ ๊ฒ๋๋ค. READ_ONCE() ์ WRITE_ONCE() ์ ์ฃผ์ ๊น์
์ฌ์ฉ์ ์ฃผ์ด์ง ์กฐ๊ฑด ๊ด๊ณ๋ฅผ ์ ์งํ๋๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค.
(*) ์ปจํธ๋กค ์์กด์ฑ์ ์ํด์ ์ปดํ์ผ๋ฌ๊ฐ ์กฐ๊ฑด๊ด๊ณ๋ฅผ ์์ ๋ฒ๋ฆฌ๋ ๊ฒ์ ๋ง์์ผ
ํฉ๋๋ค. ์ฃผ์ ๊น์ READ_ONCE() ๋ atomic{,64}_read() ์ ์ฌ์ฉ์ด ์ปจํธ๋กค
์์กด์ฑ์ด ์ฌ๋ผ์ง์ง ์๊ฒ ํ๋๋ฐ ๋์์ ์ค ์ ์์ต๋๋ค. ๋ ๋ง์ ์ ๋ณด๋ฅผ
์ํด์ "์ปดํ์ผ๋ฌ ๋ฐฐ๋ฆฌ์ด" ์น์
์ ์ฐธ๊ณ ํ์๊ธฐ ๋ฐ๋๋๋ค.
(*) ์ปจํธ๋กค ์์กด์ฑ์ ๋ณดํต ๋ค๋ฅธ ํ์
์ ๋ฐฐ๋ฆฌ์ด๋ค๊ณผ ์ง์ ๋ง์ถฐ ์ฌ์ฉ๋ฉ๋๋ค.
(*) ์ปจํธ๋กค ์์กด์ฑ์ ์ดํ์ฑ์ ์ ๊ณตํ์ง -์์ต๋๋ค-. ์ดํ์ฑ์ด ํ์ํ๋ค๋ฉด,
smp_mb() ๋ฅผ ์ฌ์ฉํ์ธ์.
SMP ๋ฐฐ๋ฆฌ์ด ์ง๋ง์ถ๊ธฐ
--------------------
CPU ๊ฐ ์ํธ์์ฉ์ ๋ค๋ฃฐ ๋์ ์ผ๋ถ ํ์
์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ ํญ์ ์ง์ ๋ง์ถฐ
์ฌ์ฉ๋์ด์ผ ํฉ๋๋ค. ์ ์ ํ๊ฒ ์ง์ ๋ง์ถ์ง ์์ ์ฝ๋๋ ์ฌ์ค์ ์๋ฌ์ ๊ฐ๊น์ต๋๋ค.
๋ฒ์ฉ ๋ฐฐ๋ฆฌ์ด๋ค์ ๋ฒ์ฉ ๋ฐฐ๋ฆฌ์ด๋ผ๋ฆฌ๋ ์ง์ ๋ง์ถ์ง๋ง ์ดํ์ฑ์ด ์๋ ๋๋ถ๋ถ์ ๋ค๋ฅธ
ํ์
์ ๋ฐฐ๋ฆฌ์ด๋ค๊ณผ๋ ์ง์ ๋ง์ถฅ๋๋ค. ACQUIRE ๋ฐฐ๋ฆฌ์ด๋ RELEASE ๋ฐฐ๋ฆฌ์ด์ ์ง์
๋ง์ถฅ๋๋ค๋ง, ๋ ๋ค ๋ฒ์ฉ ๋ฐฐ๋ฆฌ์ด๋ฅผ ํฌํจํด ๋ค๋ฅธ ๋ฐฐ๋ฆฌ์ด๋ค๊ณผ๋ ์ง์ ๋ง์ถ ์ ์์ต๋๋ค.
์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด๋ ๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๋ ์ปจํธ๋กค ์์กด์ฑ, ACQUIRE ๋ฐฐ๋ฆฌ์ด, RELEASE
๋ฐฐ๋ฆฌ์ด, ์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด, ๋๋ ๋ฒ์ฉ ๋ฐฐ๋ฆฌ์ด์ ์ง์ ๋ง์ถฅ๋๋ค. ๋น์ทํ๊ฒ ์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด๋
์ปจํธ๋กค ์์กด์ฑ, ๋๋ ๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๋ ์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด๋ ACQUIRE ๋ฐฐ๋ฆฌ์ด,
RELEASE ๋ฐฐ๋ฆฌ์ด, ๋๋ ๋ฒ์ฉ ๋ฐฐ๋ฆฌ์ด์ ์ง์ ๋ง์ถ๋๋ฐ, ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
CPU 1 CPU 2
=============== ===============
WRITE_ONCE(a, 1);
<์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด>
WRITE_ONCE(b, 2); x = READ_ONCE(b);
<์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด>
y = READ_ONCE(a);
๋๋:
CPU 1 CPU 2
=============== ===============================
a = 1;
<์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด>
WRITE_ONCE(b, &a); x = READ_ONCE(b);
<๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด>
y = *x;
๋๋:
CPU 1 CPU 2
=============== ===============================
r1 = READ_ONCE(y);
<๋ฒ์ฉ ๋ฐฐ๋ฆฌ์ด>
WRITE_ONCE(y, 1); if (r2 = READ_ONCE(x)) {
<๋ฌต์์ ์ปจํธ๋กค ์์กด์ฑ>
WRITE_ONCE(y, 1);
}
assert(r1 == 0 || r2 == 0);
๊ธฐ๋ณธ์ ์ผ๋ก, ์ฌ๊ธฐ์์ ์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด๋ "๋ ์ํ๋" ํ์
์ผ ์ ์์ด๋ ํญ์ ์กด์ฌํด์ผ
ํฉ๋๋ค.
[!] ์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด ์์ ์คํ ์ด ์คํผ๋ ์ด์
์ ์ผ๋ฐ์ ์ผ๋ก ์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด๋ ๋ฐ์ดํฐ
์์กด์ฑ ๋ฐฐ๋ฆฌ์ด ๋ค์ ๋ก๋ ์คํผ๋ ์ด์
๊ณผ ๋งค์น๋ ๊ฒ์ด๊ณ , ๋ฐ๋๋ ๋ง์ฐฌ๊ฐ์ง์
๋๋ค:
CPU 1 CPU 2
=================== ===================
WRITE_ONCE(a, 1); }---- --->{ v = READ_ONCE(c);
WRITE_ONCE(b, 2); } \ / { w = READ_ONCE(d);
<์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด> \ <์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด>
WRITE_ONCE(c, 3); } / \ { x = READ_ONCE(a);
WRITE_ONCE(d, 4); }---- --->{ y = READ_ONCE(b);
๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด ์ํ์ค์ ์
-------------------------
์ฒซ์งธ, ์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด๋ ์คํ ์ด ์คํผ๋ ์ด์
๋ค์ ๋ถ๋ถ์ ์์ ์ธ์ฐ๊ธฐ๋ก ๋์ํฉ๋๋ค.
์๋์ ์ด๋ฒคํธ ์ํ์ค๋ฅผ ๋ณด์ธ์:
CPU 1
=======================
STORE A = 1
STORE B = 2
STORE C = 3
<์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด>
STORE D = 4
STORE E = 5
์ด ์ด๋ฒคํธ ์ํ์ค๋ ๋ฉ๋ชจ๋ฆฌ ์ผ๊ด์ฑ ์์คํ
์ ์์๋ผ๋ฆฌ์ ์์๊ฐ ์กด์ฌํ์ง ์๋ ์งํฉ
{ STORE A, STORE B, STORE C } ๊ฐ ์ญ์ ์์๋ผ๋ฆฌ์ ์์๊ฐ ์กด์ฌํ์ง ์๋ ์งํฉ
{ STORE D, STORE E } ๋ณด๋ค ๋จผ์ ์ผ์ด๋ ๊ฒ์ผ๋ก ์์คํ
์ ๋๋จธ์ง ์์๋ค์ ๋ณด์ด๋๋ก
์ ๋ฌ๋ฉ๋๋ค:
+-------+ : :
| | +------+
| |------>| C=3 | } /\
| | : +------+ }----- \ -----> ์์คํ
์ ๋๋จธ์ง ์์์
| | : | A=1 | } \/ ๋ณด์ฌ์ง ์ ์๋ ์ด๋ฒคํธ๋ค
| | : +------+ }
| CPU 1 | : | B=2 | }
| | +------+ }
| | wwwwwwwwwwwwwwww } <--- ์ฌ๊ธฐ์ ์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด๋ ๋ฐฐ๋ฆฌ์ด ์์
| | +------+ } ๋ชจ๋ ์คํ ์ด๊ฐ ๋ฐฐ๋ฆฌ์ด ๋ค์ ์คํ ์ด
| | : | E=5 | } ์ ์ ๋ฉ๋ชจ๋ฆฌ ์์คํ
์ ์ ๋ฌ๋๋๋ก
| | : +------+ } ํฉ๋๋ค
| |------>| D=4 | }
| | +------+
+-------+ : :
|
| CPU 1 ์ ์ํด ๋ฉ๋ชจ๋ฆฌ ์์คํ
์ ์ ๋ฌ๋๋
| ์ผ๋ จ์ ์คํ ์ด ์คํผ๋ ์ด์
๋ค
V
๋์งธ, ๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๋ ๋ฐ์ดํฐ ์์กด์ ๋ก๋ ์คํผ๋ ์ด์
๋ค์ ๋ถ๋ถ์ ์์
์ธ์ฐ๊ธฐ๋ก ๋์ํฉ๋๋ค. ๋ค์ ์ผ๋ จ์ ์ด๋ฒคํธ๋ค์ ๋ณด์ธ์:
CPU 1 CPU 2
======================= =======================
{ B = 7; X = 9; Y = 8; C = &Y }
STORE A = 1
STORE B = 2
<์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด>
STORE C = &B LOAD X
STORE D = 4 LOAD C (gets &B)
LOAD *C (reads B)
์ฌ๊ธฐ์ ๋ณ๋ค๋ฅธ ๊ฐ์
์ด ์๋ค๋ฉด, CPU 1 ์ ์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด์๋ ๋ถ๊ตฌํ๊ณ CPU 2 ๋ CPU 1
์ ์ด๋ฒคํธ๋ค์ ์์ ํ ๋ฌด์์์ ์์๋ก ์ธ์งํ๊ฒ ๋ฉ๋๋ค:
+-------+ : : : :
| | +------+ +-------+ | CPU 2 ์ ์ธ์ง๋๋
| |------>| B=2 |----- --->| Y->8 | | ์
๋ฐ์ดํธ ์ด๋ฒคํธ
| | : +------+ \ +-------+ | ์ํ์ค
| CPU 1 | : | A=1 | \ --->| C->&Y | V
| | +------+ | +-------+
| | wwwwwwwwwwwwwwww | : :
| | +------+ | : :
| | : | C=&B |--- | : : +-------+
| | : +------+ \ | +-------+ | |
| |------>| D=4 | ----------->| C->&B |------>| |
| | +------+ | +-------+ | |
+-------+ : : | : : | |
| : : | |
| : : | CPU 2 |
| +-------+ | |
๋ถ๋ช
ํ ์๋ชป๋ ---> | | B->7 |------>| |
B ์ ๊ฐ ์ธ์ง (!) | +-------+ | |
| : : | |
| +-------+ | |
X ์ ๋ก๋๊ฐ B ์ ---> \ | X->9 |------>| |
์ผ๊ด์ฑ ์ ์ง๋ฅผ \ +-------+ | |
์ง์ฐ์ํด ----->| B->2 | +-------+
+-------+
: :
์์ ์์์, CPU 2 ๋ (B ์ ๊ฐ์ด ๋ ) *C ์ ๊ฐ ์ฝ๊ธฐ๊ฐ C ์ LOAD ๋ค์ ์ด์ด์ง์๋
B ๊ฐ 7 ์ด๋ผ๋ ๊ฒฐ๊ณผ๋ฅผ ์ป์ต๋๋ค.
ํ์ง๋ง, ๋ง์ฝ ๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๊ฐ C ์ ๋ก๋์ *C (์ฆ, B) ์ ๋ก๋ ์ฌ์ด์
์์๋ค๋ฉด:
CPU 1 CPU 2
======================= =======================
{ B = 7; X = 9; Y = 8; C = &Y }
STORE A = 1
STORE B = 2
<์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด>
STORE C = &B LOAD X
STORE D = 4 LOAD C (gets &B)
<๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด>
LOAD *C (reads B)
๋ค์๊ณผ ๊ฐ์ด ๋ฉ๋๋ค:
+-------+ : : : :
| | +------+ +-------+
| |------>| B=2 |----- --->| Y->8 |
| | : +------+ \ +-------+
| CPU 1 | : | A=1 | \ --->| C->&Y |
| | +------+ | +-------+
| | wwwwwwwwwwwwwwww | : :
| | +------+ | : :
| | : | C=&B |--- | : : +-------+
| | : +------+ \ | +-------+ | |
| |------>| D=4 | ----------->| C->&B |------>| |
| | +------+ | +-------+ | |
+-------+ : : | : : | |
| : : | |
| : : | CPU 2 |
| +-------+ | |
| | X->9 |------>| |
| +-------+ | |
C ๋ก์ ์คํ ์ด ์์ ---> \ ddddddddddddddddd | |
๋ชจ๋ ์ด๋ฒคํธ ๊ฒฐ๊ณผ๊ฐ \ +-------+ | |
๋ค์ ๋ก๋์๊ฒ ----->| B->2 |------>| |
๋ณด์ด๊ฒ ๊ฐ์ ํ๋ค +-------+ | |
: : +-------+
์
์งธ, ์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด๋ ๋ก๋ ์คํผ๋ ์ด์
๋ค์์ ๋ถ๋ถ์ ์์ ์ธ์ฐ๊ธฐ๋ก ๋์ํฉ๋๋ค.
์๋์ ์ผ๋ จ์ ์ด๋ฒคํธ๋ฅผ ๋ด
์๋ค:
CPU 1 CPU 2
======================= =======================
{ A = 0, B = 9 }
STORE A=1
<์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด>
STORE B=2
LOAD B
LOAD A
CPU 1 ์ ์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด๋ฅผ ์ณค์ง๋ง, ๋ณ๋ค๋ฅธ ๊ฐ์
์ด ์๋ค๋ฉด CPU 2 ๋ CPU 1 ์์ ํํด์ง
์ด๋ฒคํธ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฌด์์์ ์์๋ก ์ธ์งํ๊ฒ ๋ฉ๋๋ค.
+-------+ : : : :
| | +------+ +-------+
| |------>| A=1 |------ --->| A->0 |
| | +------+ \ +-------+
| CPU 1 | wwwwwwwwwwwwwwww \ --->| B->9 |
| | +------+ | +-------+
| |------>| B=2 |--- | : :
| | +------+ \ | : : +-------+
+-------+ : : \ | +-------+ | |
---------->| B->2 |------>| |
| +-------+ | CPU 2 |
| | A->0 |------>| |
| +-------+ | |
| : : +-------+
\ : :
\ +-------+
---->| A->1 |
+-------+
: :
ํ์ง๋ง, ๋ง์ฝ ์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด๊ฐ B ์ ๋ก๋์ A ์ ๋ก๋ ์ฌ์ด์ ์กด์ฌํ๋ค๋ฉด:
CPU 1 CPU 2
======================= =======================
{ A = 0, B = 9 }
STORE A=1
<์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด>
STORE B=2
LOAD B
<์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด>
LOAD A
CPU 1 ์ ์ํด ๋ง๋ค์ด์ง ๋ถ๋ถ์ ์์๊ฐ CPU 2 ์๋ ๊ทธ๋๋ก ์ธ์ง๋ฉ๋๋ค:
+-------+ : : : :
| | +------+ +-------+
| |------>| A=1 |------ --->| A->0 |
| | +------+ \ +-------+
| CPU 1 | wwwwwwwwwwwwwwww \ --->| B->9 |
| | +------+ | +-------+
| |------>| B=2 |--- | : :
| | +------+ \ | : : +-------+
+-------+ : : \ | +-------+ | |
---------->| B->2 |------>| |
| +-------+ | CPU 2 |
| : : | |
| : : | |
์ฌ๊ธฐ์ ์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด๋ ----> \ rrrrrrrrrrrrrrrrr | |
B ๋ก์ ์คํ ์ด ์ ์ \ +-------+ | |
๋ชจ๋ ๊ฒฐ๊ณผ๋ฅผ CPU 2 ์ ---->| A->1 |------>| |
๋ณด์ด๋๋ก ํ๋ค +-------+ | |
: : +-------+
๋ ์๋ฒฝํ ์ค๋ช
์ ์ํด, A ์ ๋ก๋๊ฐ ์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด ์๊ณผ ๋ค์ ์์ผ๋ฉด ์ด๋ป๊ฒ ๋ ์ง
์๊ฐํด ๋ด
์๋ค:
CPU 1 CPU 2
======================= =======================
{ A = 0, B = 9 }
STORE A=1
<์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด>
STORE B=2
LOAD B
LOAD A [first load of A]
<์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด>
LOAD A [second load of A]
A ์ ๋ก๋ ๋๊ฐ๊ฐ ๋ชจ๋ B ์ ๋ก๋ ๋ค์ ์์ง๋ง, ์๋ก ๋ค๋ฅธ ๊ฐ์ ์ป์ด์ฌ ์
์์ต๋๋ค:
+-------+ : : : :
| | +------+ +-------+
| |------>| A=1 |------ --->| A->0 |
| | +------+ \ +-------+
| CPU 1 | wwwwwwwwwwwwwwww \ --->| B->9 |
| | +------+ | +-------+
| |------>| B=2 |--- | : :
| | +------+ \ | : : +-------+
+-------+ : : \ | +-------+ | |
---------->| B->2 |------>| |
| +-------+ | CPU 2 |
| : : | |
| : : | |
| +-------+ | |
| | A->0 |------>| 1st |
| +-------+ | |
์ฌ๊ธฐ์ ์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด๋ ----> \ rrrrrrrrrrrrrrrrr | |
B ๋ก์ ์คํ ์ด ์ ์ \ +-------+ | |
๋ชจ๋ ๊ฒฐ๊ณผ๋ฅผ CPU 2 ์ ---->| A->1 |------>| 2nd |
๋ณด์ด๋๋ก ํ๋ค +-------+ | |
: : +-------+
ํ์ง๋ง CPU 1 ์์์ A ์
๋ฐ์ดํธ๋ ์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด๊ฐ ์๋ฃ๋๊ธฐ ์ ์๋ ๋ณด์ผ ์๋
์๊ธด ํฉ๋๋ค:
+-------+ : : : :
| | +------+ +-------+
| |------>| A=1 |------ --->| A->0 |
| | +------+ \ +-------+
| CPU 1 | wwwwwwwwwwwwwwww \ --->| B->9 |
| | +------+ | +-------+
| |------>| B=2 |--- | : :
| | +------+ \ | : : +-------+
+-------+ : : \ | +-------+ | |
---------->| B->2 |------>| |
| +-------+ | CPU 2 |
| : : | |
\ : : | |
\ +-------+ | |
---->| A->1 |------>| 1st |
+-------+ | |
rrrrrrrrrrrrrrrrr | |
+-------+ | |
| A->1 |------>| 2nd |
+-------+ | |
: : +-------+
์ฌ๊ธฐ์ ๋ณด์ฅ๋๋ ๊ฑด, ๋ง์ฝ B ์ ๋ก๋๊ฐ B == 2 ๋ผ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ดค๋ค๋ฉด, A ์์ ๋๋ฒ์งธ
๋ก๋๋ ํญ์ A == 1 ์ ๋ณด๊ฒ ๋ ๊ฒ์ด๋ผ๋ ๊ฒ๋๋ค. A ์์ ์ฒซ๋ฒ์งธ ๋ก๋์๋ ๊ทธ๋ฐ
๋ณด์ฅ์ด ์์ต๋๋ค; A == 0 ์ด๊ฑฐ๋ A == 1 ์ด๊ฑฐ๋ ๋ ์ค ํ๋์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ฒ ๋ ๊ฒ๋๋ค.
์ฝ๊ธฐ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด VS ๋ก๋ ์์ธก
-------------------------------
๋ง์ CPU๋ค์ด ๋ก๋๋ฅผ ์์ธก์ ์ผ๋ก (speculatively) ํฉ๋๋ค: ์ด๋ค ๋ฐ์ดํฐ๋ฅผ ๋ฉ๋ชจ๋ฆฌ์์
๋ก๋ํด์ผ ํ๊ฒ ๋ ์ง ์์ธก์ ํ๋ค๋ฉด, ํด๋น ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ๋ ์ธ์คํธ๋ญ์
์ ์ค์ ๋ก๋
์์ง ๋ง๋์ง ์์๋๋ผ๋ ๋ค๋ฅธ ๋ก๋ ์์
์ด ์์ด ๋ฒ์ค (bus) ๊ฐ ์๋ฌด ์ผ๋ ํ๊ณ ์์ง
์๋ค๋ฉด, ๊ทธ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํฉ๋๋ค. ์ดํ์ ์ค์ ๋ก๋ ์ธ์คํธ๋ญ์
์ด ์คํ๋๋ฉด CPU ๊ฐ
์ด๋ฏธ ๊ทธ ๊ฐ์ ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌธ์ ๊ทธ ๋ก๋ ์ธ์คํธ๋ญ์
์ ์ฆ์ ์๋ฃ๋ฉ๋๋ค.
ํด๋น CPU ๋ ์ค์ ๋ก๋ ๊ทธ ๊ฐ์ด ํ์์น ์์๋ค๋ ์ฌ์ค์ด ๋์ค์ ๋๋ฌ๋ ์๋ ์๋๋ฐ -
ํด๋น ๋ก๋ ์ธ์คํธ๋ญ์
์ด ๋ธ๋์น๋ก ์ฐํ๋๊ฑฐ๋ ํ์ ์ ์๊ฒ ์ฃ - , ๊ทธ๋ ๊ฒ ๋๋ฉด ์์
์ฝ์ด๋ ๊ฐ์ ๋ฒ๋ฆฌ๊ฑฐ๋ ๋์ค์ ์ฌ์ฉ์ ์ํด ์บ์์ ๋ฃ์ด๋ ์ ์์ต๋๋ค.
๋ค์์ ์๊ฐํด ๋ด
์๋ค:
CPU 1 CPU 2
======================= =======================
LOAD B
DIVIDE } ๋๋๊ธฐ ๋ช
๋ น์ ์ผ๋ฐ์ ์ผ๋ก
DIVIDE } ๊ธด ์๊ฐ์ ํ์๋ก ํฉ๋๋ค
LOAD A
๋ ์ด๋ ๊ฒ ๋ ์ ์์ต๋๋ค:
: : +-------+
+-------+ | |
--->| B->2 |------>| |
+-------+ | CPU 2 |
: :DIVIDE | |
+-------+ | |
๋๋๊ธฐ ํ๋๋ผ ๋ฐ์ ---> --->| A->0 |~~~~ | |
CPU ๋ A ์ LOAD ๋ฅผ +-------+ ~ | |
์์ธกํด์ ์ํํ๋ค : : ~ | |
: :DIVIDE | |
: : ~ | |
๋๋๊ธฐ๊ฐ ๋๋๋ฉด ---> ---> : : ~-->| |
CPU ๋ ํด๋น LOAD ๋ฅผ : : | |
์ฆ๊ฐ ์๋ฃํ๋ค : : +-------+
์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด๋ ๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๋ฅผ ๋๋ฒ์งธ ๋ก๋ ์ง์ ์ ๋๋๋ค๋ฉด:
CPU 1 CPU 2
======================= =======================
LOAD B
DIVIDE
DIVIDE
<์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด>
LOAD A
์์ธก์ผ๋ก ์ป์ด์ง ๊ฐ์ ์ฌ์ฉ๋ ๋ฐฐ๋ฆฌ์ด์ ํ์
์ ๋ฐ๋ผ์ ํด๋น ๊ฐ์ด ์ณ์์ง ๊ฒํ ๋๊ฒ
๋ฉ๋๋ค. ๋ง์ฝ ํด๋น ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ๋ณํ๊ฐ ์์๋ค๋ฉด, ์์ธก์ผ๋ก ์ป์ด๋์๋ ๊ฐ์ด
์ฌ์ฉ๋ฉ๋๋ค:
: : +-------+
+-------+ | |
--->| B->2 |------>| |
+-------+ | CPU 2 |
: :DIVIDE | |
+-------+ | |
๋๋๊ธฐ ํ๋๋ผ ๋ฐ์ ---> --->| A->0 |~~~~ | |
CPU ๋ A ์ LOAD ๋ฅผ +-------+ ~ | |
์์ธกํ๋ค : : ~ | |
: :DIVIDE | |
: : ~ | |
: : ~ | |
rrrrrrrrrrrrrrrr~ | |
: : ~ | |
: : ~-->| |
: : | |
: : +-------+
ํ์ง๋ง ๋ค๋ฅธ CPU ์์ ์
๋ฐ์ดํธ๋ ๋ฌดํจํ๊ฐ ์์๋ค๋ฉด, ๊ทธ ์์ธก์ ๋ฌดํจํ๋๊ณ ๊ทธ ๊ฐ์
๋ค์ ์ฝํ์ง๋๋ค:
: : +-------+
+-------+ | |
--->| B->2 |------>| |
+-------+ | CPU 2 |
: :DIVIDE | |
+-------+ | |
๋๋๊ธฐ ํ๋๋ผ ๋ฐ์ ---> --->| A->0 |~~~~ | |
CPU ๋ A ์ LOAD ๋ฅผ +-------+ ~ | |
์์ธกํ๋ค : : ~ | |
: :DIVIDE | |
: : ~ | |
: : ~ | |
rrrrrrrrrrrrrrrrr | |
+-------+ | |
์์ธก์ฑ ๋์์ ๋ฌดํจํ ๋๊ณ ---> --->| A->1 |------>| |
์
๋ฐ์ดํธ๋ ๊ฐ์ด ๋ค์ ์ฝํ์ง๋ค +-------+ | |
: : +-------+
์ดํ์ฑ
------
์ดํ์ฑ(transitivity)์ ์ค์ ์ ์ปดํจํฐ ์์คํ
์์ ํญ์ ์ ๊ณต๋์ง๋ ์๋, ์์
๋ง์ถ๊ธฐ์ ๋ํ ์๋นํ ์ง๊ด์ ์ธ ๊ฐ๋
์
๋๋ค. ๋ค์์ ์๊ฐ ์ดํ์ฑ์ ๋ณด์ฌ์ค๋๋ค:
CPU 1 CPU 2 CPU 3
======================= ======================= =======================
{ X = 0, Y = 0 }
STORE X=1 LOAD X STORE Y=1
<๋ฒ์ฉ ๋ฐฐ๋ฆฌ์ด> <๋ฒ์ฉ ๋ฐฐ๋ฆฌ์ด>
LOAD Y LOAD X
CPU 2 ์ X ๋ก๋๊ฐ 1์ ๋ฆฌํดํ๊ณ Y ๋ก๋๊ฐ 0์ ๋ฆฌํดํ๋ค๊ณ ํด๋ด
์๋ค. ์ด๋ CPU 2 ์
X ๋ก๋๊ฐ CPU 1 ์ X ์คํ ์ด ๋ค์ ์ด๋ฃจ์ด์ก๊ณ CPU 2 ์ Y ๋ก๋๋ CPU 3 ์ Y ์คํ ์ด
์ ์ ์ด๋ฃจ์ด์ก์์ ์๋ฏธํฉ๋๋ค. ๊ทธ๋ผ "CPU 3 ์ X ๋ก๋๋ 0์ ๋ฆฌํดํ ์ ์๋์?"
CPU 2 ์ X ๋ก๋๋ CPU 1 ์ ์คํ ์ด ํ์ ์ด๋ฃจ์ด์ก์ผ๋, CPU 3 ์ X ๋ก๋๋ 1์
๋ฆฌํดํ๋๊ฒ ์์ฐ์ค๋ฝ์ต๋๋ค. ์ด๋ฐ ์๊ฐ์ด ์ดํ์ฑ์ ํ ์์
๋๋ค: CPU A ์์ ์คํ๋
๋ก๋๊ฐ CPU B ์์์ ๊ฐ์ ๋ณ์์ ๋ํ ๋ก๋๋ฅผ ๋ค๋ฐ๋ฅธ๋ค๋ฉด, CPU A ์ ๋ก๋๋ CPU B
์ ๋ก๋๊ฐ ๋ด๋์ ๊ฐ๊ณผ ๊ฐ๊ฑฐ๋ ๊ทธ ํ์ ๊ฐ์ ๋ด๋์์ผ ํฉ๋๋ค.
๋ฆฌ๋
์ค ์ปค๋์์ ๋ฒ์ฉ ๋ฐฐ๋ฆฌ์ด์ ์ฌ์ฉ์ ์ดํ์ฑ์ ๋ณด์ฅํฉ๋๋ค. ๋ฐ๋ผ์, ์์ ์์์
CPU 2 ์ X ๋ก๋๊ฐ 1์, Y ๋ก๋๋ 0์ ๋ฆฌํดํ๋ค๋ฉด, CPU 3 ์ X ๋ก๋๋ ๋ฐ๋์ 1์
๋ฆฌํดํฉ๋๋ค.
ํ์ง๋ง, ์ฝ๊ธฐ๋ ์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด์ ๋ํด์๋ ์ดํ์ฑ์ด ๋ณด์ฅ๋์ง -์์ต๋๋ค-. ์๋ฅผ ๋ค์ด,
์์ ์์์ CPU 2 ์ ๋ฒ์ฉ ๋ฐฐ๋ฆฌ์ด๊ฐ ์๋์ฒ๋ผ ์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด๋ก ๋ฐ๋ ๊ฒฝ์ฐ๋ฅผ ์๊ฐํด
๋ด
์๋ค:
CPU 1 CPU 2 CPU 3
======================= ======================= =======================
{ X = 0, Y = 0 }
STORE X=1 LOAD X STORE Y=1
<์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด> <๋ฒ์ฉ ๋ฐฐ๋ฆฌ์ด>
LOAD Y LOAD X
์ด ์ฝ๋๋ ์ดํ์ฑ์ ๊ฐ์ง ์์ต๋๋ค: ์ด ์์์๋, CPU 2 ์ X ๋ก๋๊ฐ 1์
๋ฆฌํดํ๊ณ , Y ๋ก๋๋ 0์ ๋ฆฌํดํ์ง๋ง CPU 3 ์ X ๋ก๋๊ฐ 0์ ๋ฆฌํดํ๋ ๊ฒ๋ ์์ ํ
ํฉ๋ฒ์ ์
๋๋ค.
CPU 2 ์ ์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด๊ฐ ์์ ์ ์ฝ๊ธฐ๋ ์์๋ฅผ ๋ง์ถฐ์ค๋, CPU 1 ์ ์คํ ์ด์์
์์๋ฅผ ๋ง์ถฐ์ค๋ค๊ณ ๋ ๋ณด์ฅํ ์ ์๋ค๋๊ฒ ํต์ฌ์
๋๋ค. ๋ฐ๋ผ์, CPU 1 ๊ณผ CPU 2 ๊ฐ
๋ฒํผ๋ ์บ์๋ฅผ ๊ณต์ ํ๋ ์์คํ
์์ ์ด ์์ ์ฝ๋๊ฐ ์คํ๋๋ค๋ฉด, CPU 2 ๋ CPU 1 ์ด
์ด ๊ฐ์ ์ข ๋นจ๋ฆฌ ์ ๊ทผํ ์ ์์ ๊ฒ์
๋๋ค. ๋ฐ๋ผ์ CPU 1 ๊ณผ CPU 2 ์ ์ ๊ทผ์ผ๋ก
์กฐํฉ๋ ์์๋ฅผ ๋ชจ๋ CPU ๊ฐ ๋์ํ ์ ์๋๋ก ํ๊ธฐ ์ํด ๋ฒ์ฉ ๋ฐฐ๋ฆฌ์ด๊ฐ ํ์ํฉ๋๋ค.
๋ฒ์ฉ ๋ฐฐ๋ฆฌ์ด๋ "๊ธ๋ก๋ฒ ์ดํ์ฑ"์ ์ ๊ณตํด์, ๋ชจ๋ CPU ๋ค์ด ์คํผ๋ ์ด์
๋ค์ ์์์
๋์ํ๊ฒ ํ ๊ฒ์
๋๋ค. ๋ฐ๋ฉด, release-acquire ์กฐํฉ์ "๋ก์ปฌ ์ดํ์ฑ" ๋ง์
์ ๊ณตํด์, ํด๋น ์กฐํฉ์ด ์ฌ์ฉ๋ CPU ๋ค๋ง์ด ํด๋น ์ก์ธ์ค๋ค์ ์กฐํฉ๋ ์์์ ๋์ํจ์ด
๋ณด์ฅ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์กด๊ฒฝ์ค๋ฐ Herman Hollerith ์ C ์ฝ๋๋ก ๋ณด๋ฉด:
int u, v, x, y, z;
void cpu0(void)
{
r0 = smp_load_acquire(&x);
WRITE_ONCE(u, 1);
smp_store_release(&y, 1);
}
void cpu1(void)
{
r1 = smp_load_acquire(&y);
r4 = READ_ONCE(v);
r5 = READ_ONCE(u);
smp_store_release(&z, 1);
}
void cpu2(void)
{
r2 = smp_load_acquire(&z);
smp_store_release(&x, 1);
}
void cpu3(void)
{
WRITE_ONCE(v, 1);
smp_mb();
r3 = READ_ONCE(u);
}
cpu0(), cpu1(), ๊ทธ๋ฆฌ๊ณ cpu2() ๋ smp_store_release()/smp_load_acquire() ์์
์ฐ๊ฒฐ์ ํตํ ๋ก์ปฌ ์ดํ์ฑ์ ๋์ฐธํ๊ณ ์์ผ๋ฏ๋ก, ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๋ ๋์ค์ง ์์
๊ฒ๋๋ค:
r0 == 1 && r1 == 1 && r2 == 1
๋ ๋์๊ฐ์, cpu0() ์ cpu1() ์ฌ์ด์ release-acquire ๊ด๊ณ๋ก ์ธํด, cpu1() ์
cpu0() ์ ์ฐ๊ธฐ๋ฅผ ๋ด์ผ๋ง ํ๋ฏ๋ก, ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๋ ์์ ๊ฒ๋๋ค:
r1 == 1 && r5 == 0
ํ์ง๋ง, release-acquire ํ๋์ฑ์ ๋์ฐธํ CPU ๋ค์๋ง ์ ์ฉ๋๋ฏ๋ก cpu3() ์๋
์ ์ฉ๋์ง ์์ต๋๋ค. ๋ฐ๋ผ์, ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๊ฐ๋ฅํฉ๋๋ค:
r0 == 0 && r1 == 1 && r2 == 1 && r3 == 0 && r4 == 0
๋น์ทํ๊ฒ, ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๋ ๊ฐ๋ฅํฉ๋๋ค:
r0 == 0 && r1 == 1 && r2 == 1 && r3 == 0 && r4 == 0 && r5 == 1
cpu0(), cpu1(), ๊ทธ๋ฆฌ๊ณ cpu2() ๋ ๊ทธ๋ค์ ์ฝ๊ธฐ์ ์ฐ๊ธฐ๋ฅผ ์์๋๋ก ๋ณด๊ฒ ๋์ง๋ง,
release-acquire ์ฒด์ธ์ ๊ด์ฌ๋์ง ์์ CPU ๋ค์ ๊ทธ ์์์ ์ด๊ฒฌ์ ๊ฐ์ง ์
์์ต๋๋ค. ์ด๋ฐ ์ด๊ฒฌ์ smp_load_acquire() ์ smp_store_release() ์ ๊ตฌํ์
์ฌ์ฉ๋๋ ์ํ๋ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด ์ธ์คํธ๋ญ์
๋ค์ ํญ์ ๋ฐฐ๋ฆฌ์ด ์์ ์คํ ์ด๋ค์ ๋ค์
๋ก๋๋ค์ ์์ธ์ธ ํ์๋ ์๋ค๋ ์ฌ์ค์์ ๊ธฐ์ธํฉ๋๋ค. ์ด ๋ง์ cpu3() ๋ cpu0() ์
u ๋ก์ ์คํ ์ด๋ฅผ cpu1() ์ v ๋ก๋ถํฐ์ ๋ก๋ ๋ค์ ์ผ์ด๋ ๊ฒ์ผ๋ก ๋ณผ ์ ์๋ค๋
๋ป์
๋๋ค, cpu0() ์ cpu1() ์ ์ด ๋ ์คํผ๋ ์ด์
์ด ์๋๋ ์์๋๋ก ์ผ์ด๋ฌ์์
๋ชจ๋ ๋์ํ๋๋ฐ๋ ๋ง์
๋๋ค.
ํ์ง๋ง, smp_load_acquire() ๋ ๋ง์ ์ด ์๋์ ๋ช
์ฌํ์๊ธฐ ๋ฐ๋๋๋ค. ๊ตฌ์ฒด์ ์ผ๋ก,
์ด ํจ์๋ ๋จ์ํ ์์ ๊ท์น์ ์งํค๋ฉฐ ์ธ์๋ก๋ถํฐ์ ์ฝ๊ธฐ๋ฅผ ์ํํฉ๋๋ค. ์ด๊ฒ์
์ด๋ค ํน์ ํ ๊ฐ์ด ์ฝํ ๊ฒ์ธ์ง๋ ๋ณด์ฅํ์ง -์์ต๋๋ค-. ๋ฐ๋ผ์, ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๋
๊ฐ๋ฅํฉ๋๋ค:
r0 == 0 && r1 == 0 && r2 == 0 && r5 == 0
์ด๋ฐ ๊ฒฐ๊ณผ๋ ์ด๋ค ๊ฒ๋ ์ฌ๋ฐฐ์น ๋์ง ์๋, ์์ฐจ์ ์ผ๊ด์ฑ์ ๊ฐ์ง ๊ฐ์์
์์คํ
์์๋ ์ผ์ด๋ ์ ์์์ ๊ธฐ์ตํด ๋์๊ธฐ ๋ฐ๋๋๋ค.
๋ค์ ๋งํ์ง๋ง, ๋น์ ์ ์ฝ๋๊ฐ ๊ธ๋ก๋ฒ ์ดํ์ฑ์ ํ์๋ก ํ๋ค๋ฉด, ๋ฒ์ฉ ๋ฐฐ๋ฆฌ์ด๋ฅผ
์ฌ์ฉํ์ญ์์ค.
==================
๋ช
์์ ์ปค๋ ๋ฐฐ๋ฆฌ์ด
==================
๋ฆฌ๋
์ค ์ปค๋์ ์๋ก ๋ค๋ฅธ ๋จ๊ณ์์ ๋์ํ๋ ๋ค์ํ ๋ฐฐ๋ฆฌ์ด๋ค์ ๊ฐ์ง๊ณ ์์ต๋๋ค:
(*) ์ปดํ์ผ๋ฌ ๋ฐฐ๋ฆฌ์ด.
(*) CPU ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด.
(*) MMIO ์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด.
์ปดํ์ผ๋ฌ ๋ฐฐ๋ฆฌ์ด
---------------
๋ฆฌ๋
์ค ์ปค๋์ ์ปดํ์ผ๋ฌ๊ฐ ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค๋ฅผ ์ฌ๋ฐฐ์น ํ๋ ๊ฒ์ ๋ง์์ฃผ๋ ๋ช
์์ ์ธ
์ปดํ์ผ๋ฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค:
barrier();
์ด๊ฑด ๋ฒ์ฉ ๋ฐฐ๋ฆฌ์ด์
๋๋ค -- barrier() ์ ์ฝ๊ธฐ-์ฝ๊ธฐ ๋ ์ฐ๊ธฐ-์ฐ๊ธฐ ๋ณ์ข
์ ์์ต๋๋ค.
ํ์ง๋ง, READ_ONCE() ์ WRITE_ONCE() ๋ ํน์ ์ก์ธ์ค๋ค์ ๋ํด์๋ง ๋์ํ๋
barrier() ์ ์ํ๋ ํํ๋ก ๋ณผ ์ ์์ต๋๋ค.
barrier() ํจ์๋ ๋ค์๊ณผ ๊ฐ์ ํจ๊ณผ๋ฅผ ๊ฐ์ต๋๋ค:
(*) ์ปดํ์ผ๋ฌ๊ฐ barrier() ๋ค์ ์ก์ธ์ค๋ค์ด barrier() ์์ ์ก์ธ์ค๋ณด๋ค ์์ผ๋ก
์ฌ๋ฐฐ์น๋์ง ๋ชปํ๊ฒ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์ธํฐ๋ฝํธ ํธ๋ค๋ฌ ์ฝ๋์ ์ธํฐ๋ฝํธ ๋นํ
์ฝ๋ ์ฌ์ด์ ํต์ ์ ์ ์คํ ํ๊ธฐ ์ํด ์ฌ์ฉ๋ ์ ์์ต๋๋ค.
(*) ๋ฃจํ์์, ์ปดํ์ผ๋ฌ๊ฐ ๋ฃจํ ์กฐ๊ฑด์ ์ฌ์ฉ๋ ๋ณ์๋ฅผ ๋งค ์ดํฐ๋ ์ด์
๋ง๋ค
๋ฉ๋ชจ๋ฆฌ์์ ๋ก๋ํ์ง ์์๋ ๋๋๋ก ์ต์ ํ ํ๋๊ฑธ ๋ฐฉ์งํฉ๋๋ค.
READ_ONCE() ์ WRITE_ONCE() ํจ์๋ ์ฑ๊ธ ์ฐ๋ ๋ ์ฝ๋์์๋ ๋ฌธ์ ์์ง๋ง ๋์์ฑ์ด
์๋ ์ฝ๋์์๋ ๋ฌธ์ ๊ฐ ๋ ์ ์๋ ๋ชจ๋ ์ต์ ํ๋ฅผ ๋ง์ต๋๋ค. ์ด๋ฐ ๋ฅ์ ์ต์ ํ์
๋ํ ์๋ฅผ ๋ช๊ฐ์ง ๋ค์ด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
(*) ์ปดํ์ผ๋ฌ๋ ๊ฐ์ ๋ณ์์ ๋ํ ๋ก๋์ ์คํ ์ด๋ฅผ ์ฌ๋ฐฐ์น ํ ์ ์๊ณ , ์ด๋ค
๊ฒฝ์ฐ์๋ CPU๊ฐ ๊ฐ์ ๋ณ์๋ก๋ถํฐ์ ๋ก๋๋ค์ ์ฌ๋ฐฐ์นํ ์๋ ์์ต๋๋ค. ์ด๋
๋ค์์ ์ฝ๋๊ฐ:
a[0] = x;
a[1] = x;
x ์ ์์ ๊ฐ์ด a[1] ์, ์ ๊ฐ์ด a[0] ์ ์๊ฒ ํ ์ ์๋ค๋ ๋ป์
๋๋ค.
์ปดํ์ผ๋ฌ์ CPU๊ฐ ์ด๋ฐ ์ผ์ ๋ชปํ๊ฒ ํ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ํด์ผ ํฉ๋๋ค:
a[0] = READ_ONCE(x);
a[1] = READ_ONCE(x);
์ฆ, READ_ONCE() ์ WRITE_ONCE() ๋ ์ฌ๋ฌ CPU ์์ ํ๋์ ๋ณ์์ ๊ฐํด์ง๋
์ก์ธ์ค๋ค์ ์บ์ ์ผ๊ด์ฑ์ ์ ๊ณตํฉ๋๋ค.
(*) ์ปดํ์ผ๋ฌ๋ ๊ฐ์ ๋ณ์์ ๋ํ ์ฐ์์ ์ธ ๋ก๋๋ค์ ๋ณํฉํ ์ ์์ต๋๋ค. ๊ทธ๋ฐ
๋ณํฉ ์์
์ผ๋ก ์ปดํ์ผ๋ฌ๋ ๋ค์์ ์ฝ๋๋ฅผ:
while (tmp = a)
do_something_with(tmp);
๋ค์๊ณผ ๊ฐ์ด, ์ฑ๊ธ ์ฐ๋ ๋ ์ฝ๋์์๋ ๋ง์ด ๋์ง๋ง ๊ฐ๋ฐ์์ ์๋์ ์ ํ ๋ง์ง
์๋ ๋ฐฉํฅ์ผ๋ก "์ต์ ํ" ํ ์ ์์ต๋๋ค:
if (tmp = a)
for (;;)
do_something_with(tmp);
์ปดํ์ผ๋ฌ๊ฐ ์ด๋ฐ ์ง์ ํ์ง ๋ชปํ๊ฒ ํ๋ ค๋ฉด READ_ONCE() ๋ฅผ ์ฌ์ฉํ์ธ์:
while (tmp = READ_ONCE(a))
do_something_with(tmp);
(*) ์์ปจ๋ ๋ ์ง์คํฐ ์ฌ์ฉ๋์ด ๋ง์ ์ปดํ์ผ๋ฌ๊ฐ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ๋ ์ง์คํฐ์ ๋ด์ ์
์๋ ๊ฒฝ์ฐ, ์ปดํ์ผ๋ฌ๋ ๋ณ์๋ฅผ ๋ค์ ๋ก๋ํ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ์ปดํ์ผ๋ฌ๋
์์ ์์์ ๋ณ์ 'tmp' ์ฌ์ฉ์ ์ต์ ํ๋ก ์์ ๋ฒ๋ฆด ์ ์์ต๋๋ค:
while (tmp = a)
do_something_with(tmp);
์ด ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ด ์ฑ๊ธ ์ฐ๋ ๋์์๋ ์๋ฒฝํ์ง๋ง ๋์์ฑ์ด ์กด์ฌํ๋
๊ฒฝ์ฐ์ ์น๋ช
์ ์ธ ์ฝ๋๋ก ๋ฐ๋ ์ ์์ต๋๋ค:
while (a)
do_something_with(a);
์๋ฅผ ๋ค์ด, ์ต์ ํ๋ ์ด ์ฝ๋๋ ๋ณ์ a ๊ฐ ๋ค๋ฅธ CPU ์ ์ํด "while" ๋ฌธ๊ณผ
do_something_with() ํธ์ถ ์ฌ์ด์ ๋ฐ๋์ด do_something_with() ์ 0์ ๋๊ธธ
์๋ ์์ต๋๋ค.
์ด๋ฒ์๋, ์ปดํ์ผ๋ฌ๊ฐ ๊ทธ๋ฐ ์ง์ ํ๋๊ฑธ ๋ง๊ธฐ ์ํด READ_ONCE() ๋ฅผ ์ฌ์ฉํ์ธ์:
while (tmp = READ_ONCE(a))
do_something_with(tmp);
๋ ์ง์คํฐ๊ฐ ๋ถ์กฑํ ์ํฉ์ ๊ฒช๋ ๊ฒฝ์ฐ, ์ปดํ์ผ๋ฌ๋ tmp ๋ฅผ ์คํ์ ์ ์ฅํด๋ ์๋
์์ต๋๋ค. ์ปดํ์ผ๋ฌ๊ฐ ๋ณ์๋ฅผ ๋ค์ ์ฝ์ด๋ค์ด๋๊ฑด ์ด๋ ๊ฒ ์ ์ฅํด๋๊ณ ํ์ ๋ค์
์ฝ์ด๋ค์ด๋๋ฐ ๋๋ ์ค๋ฒํค๋ ๋๋ฌธ์
๋๋ค. ๊ทธ๋ ๊ฒ ํ๋๊ฒ ์ฑ๊ธ ์ฐ๋ ๋
์ฝ๋์์๋ ์์ ํ๋ฏ๋ก, ์์ ํ์ง ์์ ๊ฒฝ์ฐ์๋ ์ปดํ์ผ๋ฌ์๊ฒ ์ง์ ์๋ ค์ค์ผ
ํฉ๋๋ค.
(*) ์ปดํ์ผ๋ฌ๋ ๊ทธ ๊ฐ์ด ๋ฌด์์ผ์ง ์๊ณ ์๋ค๋ฉด ๋ก๋๋ฅผ ์์ ์ํ ์๋ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด, ๋ค์์ ์ฝ๋๋ ๋ณ์ 'a' ์ ๊ฐ์ด ํญ์ 0์์ ์ฆ๋ช
ํ ์ ์๋ค๋ฉด:
while (tmp = a)
do_something_with(tmp);
์ด๋ ๊ฒ ์ต์ ํ ๋์ด๋ฒ๋ฆด ์ ์์ต๋๋ค:
do { } while (0);
์ด ๋ณํ์ ์ฑ๊ธ ์ฐ๋ ๋ ์ฝ๋์์๋ ๋์์ด ๋๋๋ฐ ๋ก๋์ ๋ธ๋์น๋ฅผ ์ ๊ฑฐํ๊ธฐ
๋๋ฌธ์
๋๋ค. ๋ฌธ์ ๋ ์ปดํ์ผ๋ฌ๊ฐ 'a' ์ ๊ฐ์ ์
๋ฐ์ดํธ ํ๋๊ฑด ํ์ฌ์ CPU ํ๋
๋ฟ์ด๋ผ๋ ๊ฐ์ ์์์ ์ฆ๋ช
์ ํ๋ค๋๋ฐ ์์ต๋๋ค. ๋ง์ฝ ๋ณ์ 'a' ๊ฐ ๊ณต์ ๋์ด
์๋ค๋ฉด, ์ปดํ์ผ๋ฌ์ ์ฆ๋ช
์ ํ๋ฆฐ ๊ฒ์ด ๋ ๊ฒ๋๋ค. ์ปดํ์ผ๋ฌ๋ ๊ทธ ์์ ์ด
์๊ฐํ๋ ๊ฒ๋งํผ ๋ง์ ๊ฒ์ ์๊ณ ์์ง ๋ชปํจ์ ์ปดํ์ผ๋ฌ์๊ฒ ์๋ฆฌ๊ธฐ ์ํด
READ_ONCE() ๋ฅผ ์ฌ์ฉํ์ธ์:
while (tmp = READ_ONCE(a))
do_something_with(tmp);
ํ์ง๋ง ์ปดํ์ผ๋ฌ๋ READ_ONCE() ๋ค์ ๋์ค๋ ๊ฐ์ ๋ํด์๋ ๋๊ธธ์ ๋๊ณ ์์์
๊ธฐ์ตํ์ธ์. ์๋ฅผ ๋ค์ด, ๋ค์์ ์ฝ๋์์ MAX ๋ ์ ์ฒ๋ฆฌ๊ธฐ ๋งคํฌ๋ก๋ก, 1์ ๊ฐ์
๊ฐ๋๋ค๊ณ ํด๋ด
์๋ค:
while ((tmp = READ_ONCE(a)) % MAX)
do_something_with(tmp);
์ด๋ ๊ฒ ๋๋ฉด ์ปดํ์ผ๋ฌ๋ MAX ๋ฅผ ๊ฐ์ง๊ณ ์ํ๋๋ "%" ์คํผ๋ ์ดํฐ์ ๊ฒฐ๊ณผ๊ฐ ํญ์
0์ด๋ผ๋ ๊ฒ์ ์๊ฒ ๋๊ณ , ์ปดํ์ผ๋ฌ๊ฐ ์ฝ๋๋ฅผ ์ค์ง์ ์ผ๋ก๋ ์กด์ฌํ์ง ์๋
๊ฒ์ฒ๋ผ ์ต์ ํ ํ๋ ๊ฒ์ด ํ์ฉ๋์ด ๋ฒ๋ฆฝ๋๋ค. ('a' ๋ณ์์ ๋ก๋๋ ์ฌ์ ํ
ํํด์ง ๊ฒ๋๋ค.)
(*) ๋น์ทํ๊ฒ, ์ปดํ์ผ๋ฌ๋ ๋ณ์๊ฐ ์ ์ฅํ๋ ค ํ๋ ๊ฐ์ ์ด๋ฏธ ๊ฐ์ง๊ณ ์๋ค๋ ๊ฒ์
์๋ฉด ์คํ ์ด ์์ฒด๋ฅผ ์ ๊ฑฐํ ์ ์์ต๋๋ค. ์ด๋ฒ์๋, ์ปดํ์ผ๋ฌ๋ ํ์ฌ์ CPU
๋ง์ด ๊ทธ ๋ณ์์ ๊ฐ์ ์ฐ๋ ์ค๋ก์ง ํ๋์ ์กด์ฌ๋ผ๊ณ ์๊ฐํ์ฌ ๊ณต์ ๋ ๋ณ์์
๋ํด์๋ ์๋ชป๋ ์ผ์ ํ๊ฒ ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด, ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ์ฐ๊ฐ ์์ ์
์์ต๋๋ค:
a = 0;
... ๋ณ์ a ์ ์คํ ์ด๋ฅผ ํ์ง ์๋ ์ฝ๋ ...
a = 0;
์ปดํ์ผ๋ฌ๋ ๋ณ์ 'a' ์ ๊ฐ์ ์ด๋ฏธ 0์ด๋ผ๋ ๊ฒ์ ์๊ณ , ๋ฐ๋ผ์ ๋๋ฒ์งธ ์คํ ์ด๋ฅผ
์ญ์ ํ ๊ฒ๋๋ค. ๋ง์ฝ ๋ค๋ฅธ CPU ๊ฐ ๊ทธ ์ฌ์ด ๋ณ์ 'a' ์ ๋ค๋ฅธ ๊ฐ์ ์ผ๋ค๋ฉด
ํฉ๋นํ ๊ฒฐ๊ณผ๊ฐ ๋์ฌ ๊ฒ๋๋ค.
์ปดํ์ผ๋ฌ๊ฐ ๊ทธ๋ฐ ์๋ชป๋ ์ถ์ธก์ ํ์ง ์๋๋ก WRITE_ONCE() ๋ฅผ ์ฌ์ฉํ์ธ์:
WRITE_ONCE(a, 0);
... ๋ณ์ a ์ ์คํ ์ด๋ฅผ ํ์ง ์๋ ์ฝ๋ ...
WRITE_ONCE(a, 0);
(*) ์ปดํ์ผ๋ฌ๋ ํ์ง ๋ง๋ผ๊ณ ํ์ง ์์ผ๋ฉด ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค๋ค์ ์ฌ๋ฐฐ์น ํ ์
์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๋ค์์ ํ๋ก์ธ์ค ๋ ๋ฒจ ์ฝ๋์ ์ธํฐ๋ฝํธ ํธ๋ค๋ฌ ์ฌ์ด์
์ํธ์์ฉ์ ์๊ฐํด ๋ด
์๋ค:
void process_level(void)
{
msg = get_message();
flag = true;
}
void interrupt_handler(void)
{
if (flag)
process_message(msg);
}
์ด ์ฝ๋์๋ ์ปดํ์ผ๋ฌ๊ฐ process_level() ์ ๋ค์๊ณผ ๊ฐ์ด ๋ณํํ๋ ๊ฒ์ ๋ง์
์๋จ์ด ์๊ณ , ์ด๋ฐ ๋ณํ์ ์ฑ๊ธ์ฐ๋ ๋์์๋ผ๋ฉด ์ค์ ๋ก ํ๋ฅญํ ์ ํ์ผ ์
์์ต๋๋ค:
void process_level(void)
{
flag = true;
msg = get_message();
}
์ด ๋๊ฐ์ ๋ฌธ์ฅ ์ฌ์ด์ ์ธํฐ๋ฝํธ๊ฐ ๋ฐ์ํ๋ค๋ฉด, interrupt_handler() ๋ ์๋ฏธ๋ฅผ
์ ์ ์๋ ๋ฉ์ธ์ง๋ฅผ ๋ฐ์ ์๋ ์์ต๋๋ค. ์ด๊ฑธ ๋ง๊ธฐ ์ํด ๋ค์๊ณผ ๊ฐ์ด
WRITE_ONCE() ๋ฅผ ์ฌ์ฉํ์ธ์:
void process_level(void)
{
WRITE_ONCE(msg, get_message());
WRITE_ONCE(flag, true);
}
void interrupt_handler(void)
{
if (READ_ONCE(flag))
process_message(READ_ONCE(msg));
}
interrupt_handler() ์์์๋ ์ค์ฒฉ๋ ์ธํฐ๋ฝํธ๋ NMI ์ ๊ฐ์ด ์ธํฐ๋ฝํธ ํธ๋ค๋ฌ
์ญ์ 'flag' ์ 'msg' ์ ์ ๊ทผํ๋ ๋๋ค๋ฅธ ๋ฌด์ธ๊ฐ์ ์ธํฐ๋ฝํธ ๋ ์ ์๋ค๋ฉด
READ_ONCE() ์ WRITE_ONCE() ๋ฅผ ์ฌ์ฉํด์ผ ํจ์ ๊ธฐ์ตํด ๋์ธ์. ๋ง์ฝ ๊ทธ๋ฐ
๊ฐ๋ฅ์ฑ์ด ์๋ค๋ฉด, interrupt_handler() ์์์๋ ๋ฌธ์ํ ๋ชฉ์ ์ด ์๋๋ผ๋ฉด
READ_ONCE() ์ WRITE_ONCE() ๋ ํ์์น ์์ต๋๋ค. (๊ทผ๋์ ๋ฆฌ๋
์ค ์ปค๋์์
์ค์ฒฉ๋ ์ธํฐ๋ฝํธ๋ ๋ณดํต ์ ์ผ์ด๋์ง ์์๋ ๊ธฐ์ตํด ๋์ธ์, ์ค์ ๋ก, ์ด๋ค
์ธํฐ๋ฝํธ ํธ๋ค๋ฌ๊ฐ ์ธํฐ๋ฝํธ๊ฐ ํ์ฑํ๋ ์ฑ๋ก ๋ฆฌํดํ๋ฉด WARN_ONCE() ๊ฐ
์คํ๋ฉ๋๋ค.)
์ปดํ์ผ๋ฌ๋ READ_ONCE() ์ WRITE_ONCE() ๋ค์ READ_ONCE() ๋ WRITE_ONCE(),
barrier(), ๋๋ ๋น์ทํ ๊ฒ๋ค์ ๋ด๊ณ ์์ง ์์ ์ฝ๋๋ฅผ ์์ง์ผ ์ ์์ ๊ฒ์ผ๋ก
๊ฐ์ ๋์ด์ผ ํฉ๋๋ค.
์ด ํจ๊ณผ๋ barrier() ๋ฅผ ํตํด์๋ ๋ง๋ค ์ ์์ง๋ง, READ_ONCE() ์
WRITE_ONCE() ๊ฐ ์ข ๋ ์๋ชฉ ๋์ ์ ํ์
๋๋ค: READ_ONCE() ์ WRITE_ONCE()๋
์ปดํ์ผ๋ฌ์ ์ฃผ์ด์ง ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ๋ํด์๋ง ์ต์ ํ ๊ฐ๋ฅ์ฑ์ ํฌ๊ธฐํ๋๋ก
ํ์ง๋ง, barrier() ๋ ์ปดํ์ผ๋ฌ๊ฐ ์ง๊ธ๊น์ง ๊ธฐ๊ณ์ ๋ ์ง์คํฐ์ ์บ์ํด ๋์
๋ชจ๋ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ๊ฐ์ ๋ฒ๋ ค์ผ ํ๊ฒ ํ๊ธฐ ๋๋ฌธ์
๋๋ค. ๋ฌผ๋ก , ์ปดํ์ผ๋ฌ๋
READ_ONCE() ์ WRITE_ONCE() ๊ฐ ์ผ์ด๋ ์์๋ ์ง์ผ์ค๋๋ค, CPU ๋ ๋น์ฐํ
๊ทธ ์์๋ฅผ ์งํฌ ์๋ฌด๊ฐ ์์ง๋ง์.
(*) ์ปดํ์ผ๋ฌ๋ ๋ค์์ ์์์์ ๊ฐ์ด ๋ณ์์์ ์คํ ์ด๋ฅผ ๋ ์กฐํด๋ผ ์๋ ์์ต๋๋ค:
if (a)
b = a;
else
b = 42;
์ปดํ์ผ๋ฌ๋ ์๋์ ๊ฐ์ ์ต์ ํ๋ก ๋ธ๋์น๋ฅผ ์ค์ผ ๊ฒ๋๋ค:
b = 42;
if (a)
b = a;
์ฑ๊ธ ์ฐ๋ ๋ ์ฝ๋์์ ์ด ์ต์ ํ๋ ์์ ํ ๋ฟ ์๋๋ผ ๋ธ๋์น ๊ฐฏ์๋ฅผ
์ค์ฌ์ค๋๋ค. ํ์ง๋ง ์ํ๊น๊ฒ๋, ๋์์ฑ์ด ์๋ ์ฝ๋์์๋ ์ด ์ต์ ํ๋ ๋ค๋ฅธ
CPU ๊ฐ 'b' ๋ฅผ ๋ก๋ํ ๋, -- 'a' ๊ฐ 0์ด ์๋๋ฐ๋ -- ๊ฐ์ง์ธ ๊ฐ, 42๋ฅผ ๋ณด๊ฒ
๋๋ ๊ฒฝ์ฐ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค. ์ด๊ฑธ ๋ฐฉ์งํ๊ธฐ ์ํด WRITE_ONCE() ๋ฅผ
์ฌ์ฉํ์ธ์:
if (a)
WRITE_ONCE(b, a);
else
WRITE_ONCE(b, 42);
์ปดํ์ผ๋ฌ๋ ๋ก๋๋ฅผ ๋ง๋ค์ด๋ผ ์๋ ์์ต๋๋ค. ์ผ๋ฐ์ ์ผ๋ก๋ ๋ฌธ์ ๋ฅผ ์ผ์ผํค์ง
์์ง๋ง, ์บ์ ๋ผ์ธ ๋ฐ์ด์ฑ์ ์ผ์ผ์ผ ์ฑ๋ฅ๊ณผ ํ์ฅ์ฑ์ ๋จ์ด๋จ๋ฆด ์ ์์ต๋๋ค.
๋ ์กฐ๋ ๋ก๋๋ฅผ ๋ง๊ธฐ ์ํด์ READ_ONCE() ๋ฅผ ์ฌ์ฉํ์ธ์.
(*) ์ ๋ ฌ๋ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์์ ์์นํ, ํ๋ฒ์ ๋ฉ๋ชจ๋ฆฌ ์ฐธ์กฐ ์ธ์คํธ๋ญ์
์ผ๋ก ์ก์ธ์ค
๊ฐ๋ฅํ ํฌ๊ธฐ์ ๋ฐ์ดํฐ๋ ํ๋์ ํฐ ์ก์ธ์ค๊ฐ ์ฌ๋ฌ๊ฐ์ ์์ ์ก์ธ์ค๋ค๋ก
๋์ฒด๋๋ "๋ก๋ ํฐ์ด๋ง(load tearing)" ๊ณผ "์คํ ์ด ํฐ์ด๋ง(store tearing)" ์
๋ฐฉ์งํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์ฃผ์ด์ง ์ํคํ
์ณ๊ฐ 7-bit imeediate field ๋ฅผ ๊ฐ๋
16-bit ์คํ ์ด ์ธ์คํธ๋ญ์
์ ์ ๊ณตํ๋ค๋ฉด, ์ปดํ์ผ๋ฌ๋ ๋ค์์ 32-bit ์คํ ์ด๋ฅผ
๊ตฌํํ๋๋ฐ์ ๋๊ฐ์ 16-bit store-immediate ๋ช
๋ น์ ์ฌ์ฉํ๋ ค ํ ๊ฒ๋๋ค:
p = 0x00010002;
์คํ ์ด ํ ์์๋ฅผ ๋ง๋ค๊ณ ๊ทธ ๊ฐ์ ์คํ ์ด ํ๊ธฐ ์ํด ๋๊ฐ๊ฐ ๋๋ ์ธ์คํธ๋ญ์
์
์ฌ์ฉํ๊ฒ ๋๋, ์ด๋ฐ ์ข
๋ฅ์ ์ต์ ํ๋ฅผ GCC ๋ ์ค์ ๋ก ํจ์ ๋ถ๋ ์์ ๋์ญ์์ค.
์ด ์ต์ ํ๋ ์ฑ๊ธ ์ฐ๋ ๋ ์ฝ๋์์๋ ์ฑ๊ณต์ ์ธ ์ต์ ํ ์
๋๋ค. ์ค์ ๋ก, ๊ทผ๋์
๋ฐ์ํ (๊ทธ๋ฆฌ๊ณ ๊ณ ์ณ์ง) ๋ฒ๊ทธ๋ GCC ๊ฐ volatile ์คํ ์ด์ ๋น์ ์์ ์ผ๋ก ์ด
์ต์ ํ๋ฅผ ์ฌ์ฉํ๊ฒ ํ์ต๋๋ค. ๊ทธ๋ฐ ๋ฒ๊ทธ๊ฐ ์๋ค๋ฉด, ๋ค์์ ์์์
WRITE_ONCE() ์ ์ฌ์ฉ์ ์คํ ์ด ํฐ์ด๋ง์ ๋ฐฉ์งํฉ๋๋ค:
WRITE_ONCE(p, 0x00010002);
Packed ๊ตฌ์กฐ์ฒด์ ์ฌ์ฉ ์ญ์ ๋ค์์ ์์ฒ๋ผ ๋ก๋ / ์คํ ์ด ํฐ์ด๋ง์ ์ ๋ฐํ ์
์์ต๋๋ค:
struct __attribute__((__packed__)) foo {
short a;
int b;
short c;
};
struct foo foo1, foo2;
...
foo2.a = foo1.a;
foo2.b = foo1.b;
foo2.c = foo1.c;
READ_ONCE() ๋ WRITE_ONCE() ๋ ์๊ณ volatile ๋งํน๋ ์๊ธฐ ๋๋ฌธ์,
์ปดํ์ผ๋ฌ๋ ์ด ์ธ๊ฐ์ ๋์
๋ฌธ์ ๋๊ฐ์ 32-bit ๋ก๋์ ๋๊ฐ์ 32-bit ์คํ ์ด๋ก
๋ณํํ ์ ์์ต๋๋ค. ์ด๋ 'foo1.b' ์ ๊ฐ์ ๋ก๋ ํฐ์ด๋ง๊ณผ 'foo2.b' ์
์คํ ์ด ํฐ์ด๋ง์ ์ด๋ํ ๊ฒ๋๋ค. ์ด ์์์๋ READ_ONCE() ์ WRITE_ONCE()
๊ฐ ํฐ์ด๋ง์ ๋ง์ ์ ์์ต๋๋ค:
foo2.a = foo1.a;
WRITE_ONCE(foo2.b, READ_ONCE(foo1.b));
foo2.c = foo1.c;
๊ทธ๋ ์ง๋ง, volatile ๋ก ๋งํฌ๋ ๋ณ์์ ๋ํด์๋ READ_ONCE() ์ WRITE_ONCE() ๊ฐ
ํ์์น ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, 'jiffies' ๋ volatile ๋ก ๋งํฌ๋์ด ์๊ธฐ ๋๋ฌธ์,
READ_ONCE(jiffies) ๋ผ๊ณ ํ ํ์๊ฐ ์์ต๋๋ค. READ_ONCE() ์ WRITE_ONCE() ๊ฐ
์ค์ volatile ์บ์คํ
์ผ๋ก ๊ตฌํ๋์ด ์์ด์ ์ธ์๊ฐ ์ด๋ฏธ volatile ๋ก ๋งํฌ๋์ด
์๋ค๋ฉด ๋๋ค๋ฅธ ํจ๊ณผ๋ฅผ ๋ด์ง๋ ์๊ธฐ ๋๋ฌธ์
๋๋ค.
์ด ์ปดํ์ผ๋ฌ ๋ฐฐ๋ฆฌ์ด๋ค์ CPU ์๋ ์ง์ ์ ํจ๊ณผ๋ฅผ ์ ํ ๋ง๋ค์ง ์๊ธฐ ๋๋ฌธ์, ๊ฒฐ๊ตญ์
์ฌ๋ฐฐ์น๊ฐ ์ผ์ด๋ ์๋ ์์์ ๋ถ๋ ๊ธฐ์ตํด ๋์ญ์์ค.
CPU ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด
-----------------
๋ฆฌ๋
์ค ์ปค๋์ ๋ค์์ ์ฌ๋๊ฐ ๊ธฐ๋ณธ CPU ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค:
TYPE MANDATORY SMP CONDITIONAL
=============== ======================= ===========================
๋ฒ์ฉ mb() smp_mb()
์ฐ๊ธฐ wmb() smp_wmb()
์ฝ๊ธฐ rmb() smp_rmb()
๋ฐ์ดํฐ ์์กด์ฑ read_barrier_depends() smp_read_barrier_depends()
๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๋ฅผ ์ ์ธํ ๋ชจ๋ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ ์ปดํ์ผ๋ฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ
ํฌํจํฉ๋๋ค. ๋ฐ์ดํฐ ์์กด์ฑ์ ์ปดํ์ผ๋ฌ์์ ์ถ๊ฐ์ ์ธ ์์ ๋ณด์ฅ์ ํฌํจํ์ง
์์ต๋๋ค.
๋ฐฉ๋ฐฑ: ๋ฐ์ดํฐ ์์กด์ฑ์ด ์๋ ๊ฒฝ์ฐ, ์ปดํ์ผ๋ฌ๋ ํด๋น ๋ก๋๋ฅผ ์ฌ๋ฐ๋ฅธ ์์๋ก ์ผ์ผํฌ
๊ฒ์ผ๋ก (์: `a[b]` ๋ a[b] ๋ฅผ ๋ก๋ ํ๊ธฐ ์ ์ b ์ ๊ฐ์ ๋จผ์ ๋ก๋ํ๋ค)
๊ธฐ๋๋์ง๋ง, C ์ธ์ด ์ฌ์์๋ ์ปดํ์ผ๋ฌ๊ฐ b ์ ๊ฐ์ ์ถ์ธก (์: 1 ๊ณผ ๊ฐ์) ํด์
b ๋ก๋ ์ ์ a ๋ก๋๋ฅผ ํ๋ ์ฝ๋ (์: tmp = a[1]; if (b != 1) tmp = a[b]; ) ๋ฅผ
๋ง๋ค์ง ์์์ผ ํ๋ค๋ ๋ด์ฉ ๊ฐ์ ๊ฑด ์์ต๋๋ค. ๋ํ ์ปดํ์ผ๋ฌ๋ a[b] ๋ฅผ ๋ก๋ํ
ํ์ b ๋ฅผ ๋๋ค์ ๋ก๋ํ ์๋ ์์ด์, a[b] ๋ณด๋ค ์ต์ ๋ฒ์ ์ b ๊ฐ์ ๊ฐ์ง ์๋
์์ต๋๋ค. ์ด๋ฐ ๋ฌธ์ ๋ค์ ํด๊ฒฐ์ฑ
์ ๋ํ ์๊ฒฌ ์ผ์น๋ ์์ง ์์ต๋๋ค๋ง, ์ผ๋จ
READ_ONCE() ๋งคํฌ๋ก๋ถํฐ ๋ณด๊ธฐ ์์ํ๋๊ฒ ์ข์ ์์์ด ๋ ๊ฒ๋๋ค.
SMP ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ค์ ์ ๋ํ๋ก์ธ์๋ก ์ปดํ์ผ๋ ์์คํ
์์๋ ์ปดํ์ผ๋ฌ ๋ฐฐ๋ฆฌ์ด๋ก
๋ฐ๋๋๋ฐ, ํ๋์ CPU ๋ ์ค์ค๋ก ์ผ๊ด์ฑ์ ์ ์งํ๊ณ , ๊ฒน์น๋ ์ก์ธ์ค๋ค ์ญ์ ์ฌ๋ฐ๋ฅธ
์์๋ก ํํด์ง ๊ฒ์ผ๋ก ์๊ฐ๋๊ธฐ ๋๋ฌธ์
๋๋ค. ํ์ง๋ง, ์๋์ "Virtual Machine
Guests" ์๋ธ์น์
์ ์ฐธ๊ณ ํ์ญ์์ค.
[!] SMP ์์คํ
์์ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ๋ก์ ์ ๊ทผ๋ค์ ์์ ์ธ์์ผ ํ ๋, SMP ๋ฉ๋ชจ๋ฆฌ
๋ฐฐ๋ฆฌ์ด๋ _๋ฐ๋์_ ์ฌ์ฉ๋์ด์ผ ํจ์ ๊ธฐ์ตํ์ธ์, ๊ทธ๋์ ๋ฝ์ ์ฌ์ฉํ๋ ๊ฒ์ผ๋ก๋
์ถฉ๋ถํ๊ธด ํ์ง๋ง ๋ง์ด์ฃ .
Mandatory ๋ฐฐ๋ฆฌ์ด๋ค์ SMP ์์คํ
์์๋ UP ์์คํ
์์๋ SMP ํจ๊ณผ๋ง ํต์ ํ๊ธฐ์๋
๋ถํ์ํ ์ค๋ฒํค๋๋ฅผ ๊ฐ๊ธฐ ๋๋ฌธ์ SMP ํจ๊ณผ๋ง ํต์ ํ๋ฉด ๋๋ ๊ณณ์๋ ์ฌ์ฉ๋์ง ์์์ผ
ํฉ๋๋ค. ํ์ง๋ง, ๋์จํ ์์ ๊ท์น์ ๋ฉ๋ชจ๋ฆฌ I/O ์๋์ฐ๋ฅผ ํตํ MMIO ์ ํจ๊ณผ๋ฅผ
ํต์ ํ ๋์๋ mandatory ๋ฐฐ๋ฆฌ์ด๋ค์ด ์ฌ์ฉ๋ ์ ์์ต๋๋ค. ์ด ๋ฐฐ๋ฆฌ์ด๋ค์
์ปดํ์ผ๋ฌ์ CPU ๋ชจ๋ ์ฌ๋ฐฐ์น๋ฅผ ๋ชปํ๋๋ก ํจ์ผ๋ก์จ ๋ฉ๋ชจ๋ฆฌ ์คํผ๋ ์ด์
๋ค์ด ๋๋ฐ์ด์ค์
๋ณด์ฌ์ง๋ ์์์๋ ์ํฅ์ ์ฃผ๊ธฐ ๋๋ฌธ์, SMP ๊ฐ ์๋ ์์คํ
์ด๋ผ ํ ์ง๋ผ๋ ํ์ํ ์
์์ต๋๋ค.
์ผ๋ถ ๊ณ ๊ธ ๋ฐฐ๋ฆฌ์ด ํจ์๋ค๋ ์์ต๋๋ค:
(*) smp_store_mb(var, value)
์ด ํจ์๋ ํน์ ๋ณ์์ ํน์ ๊ฐ์ ๋์
ํ๊ณ ๋ฒ์ฉ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ ์นฉ๋๋ค.
UP ์ปดํ์ผ์์๋ ์ปดํ์ผ๋ฌ ๋ฐฐ๋ฆฌ์ด๋ณด๋ค ๋ํ ๊ฒ์ ์น๋ค๊ณ ๋ ๋ณด์ฅ๋์ง ์์ต๋๋ค.
(*) smp_mb__before_atomic();
(*) smp_mb__after_atomic();
์ด๊ฒ๋ค์ ๊ฐ์ ๋ฆฌํดํ์ง ์๋ (๋ํ๊ธฐ, ๋นผ๊ธฐ, ์ฆ๊ฐ, ๊ฐ์์ ๊ฐ์) ์ดํ ๋ฏน
ํจ์๋ค์ ์ํ, ํนํ ๊ทธ๊ฒ๋ค์ด ๋ ํผ๋ฐ์ค ์นด์ดํ
์ ์ฌ์ฉ๋ ๋๋ฅผ ์ํ
ํจ์๋ค์
๋๋ค. ์ด ํจ์๋ค์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ ๋ดํฌํ๊ณ ์์ง๋ ์์ต๋๋ค.
์ด๊ฒ๋ค์ ๊ฐ์ ๋ฆฌํดํ์ง ์์ผ๋ฉฐ ์ดํ ๋ฏนํ (set_bit ๊ณผ clear_bit ๊ฐ์) ๋นํธ
์ฐ์ฐ์๋ ์ฌ์ฉ๋ ์ ์์ต๋๋ค.
ํ ์๋ก, ๊ฐ์ฒด ํ๋๋ฅผ ๋ฌดํจํ ๊ฒ์ผ๋ก ํ์ํ๊ณ ๊ทธ ๊ฐ์ฒด์ ๋ ํผ๋ฐ์ค ์นด์ดํธ๋ฅผ
๊ฐ์์ํค๋ ๋ค์ ์ฝ๋๋ฅผ ๋ณด์ธ์:
obj->dead = 1;
smp_mb__before_atomic();
atomic_dec(&obj->ref_count);
์ด ์ฝ๋๋ ๊ฐ์ฒด์ ์
๋ฐ์ดํธ๋ death ๋งํฌ๊ฐ ๋ ํผ๋ฐ์ค ์นด์ดํฐ ๊ฐ์ ๋์
*์ ์* ๋ณด์ผ ๊ฒ์ ๋ณด์ฅํฉ๋๋ค.
๋ ๋ง์ ์ ๋ณด๋ฅผ ์ํด์ Documentation/atomic_ops.txt ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์ธ์.
์ด๋์ ์ด๊ฒ๋ค์ ์ฌ์ฉํด์ผ ํ ์ง ๊ถ๊ธํ๋ค๋ฉด "์ดํ ๋ฏน ์คํผ๋ ์ด์
" ์๋ธ์น์
์
์ฐธ๊ณ ํ์ธ์.
(*) lockless_dereference();
์ด ํจ์๋ smp_read_barrier_depends() ๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๋ฅผ ์ฌ์ฉํ๋
ํฌ์ธํฐ ์ฝ์ด์ค๊ธฐ ๋ํผ(wrapper) ํจ์๋ก ์๊ฐ๋ ์ ์์ต๋๋ค.
๊ฐ์ฒด์ ๋ผ์ดํํ์์ด RCU ์ธ์ ๋ฉ์ปค๋์ฆ์ผ๋ก ๊ด๋ฆฌ๋๋ค๋ ์ ์ ์ ์ธํ๋ฉด
rcu_dereference() ์๋ ์ ์ฌํ๋ฐ, ์๋ฅผ ๋ค๋ฉด ๊ฐ์ฒด๊ฐ ์์คํ
์ด ๊บผ์ง ๋์๋ง
์ ๊ฑฐ๋๋ ๊ฒฝ์ฐ ๋ฑ์
๋๋ค. ๋ํ, lockless_dereference() ์ RCU ์ ํจ๊ป
์ฌ์ฉ๋ ์๋, RCU ์์ด ์ฌ์ฉ๋ ์๋ ์๋ ์ผ๋ถ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ์ฌ์ฉ๋๊ณ
์์ต๋๋ค.
(*) dma_wmb();
(*) dma_rmb();
์ด๊ฒ๋ค์ CPU ์ DMA ๊ฐ๋ฅํ ๋๋ฐ์ด์ค์์ ๋ชจ๋ ์ก์ธ์ค ๊ฐ๋ฅํ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ์
์ฝ๊ธฐ, ์ฐ๊ธฐ ์์
๋ค์ ์์๋ฅผ ๋ณด์ฅํ๊ธฐ ์ํด consistent memory ์์ ์ฌ์ฉํ๊ธฐ
์ํ ๊ฒ๋ค์
๋๋ค.
์๋ฅผ ๋ค์ด, ๋๋ฐ์ด์ค์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ณต์ ํ๋ฉฐ, ๋์คํฌ๋ฆฝํฐ ์ํ ๊ฐ์ ์ฌ์ฉํด
๋์คํฌ๋ฆฝํฐ๊ฐ ๋๋ฐ์ด์ค์ ์ํด ์๋์ง ์๋๋ฉด CPU ์ ์ํด ์๋์ง ํ์ํ๊ณ ,
๊ณต์ง์ฉ ์ด์ธ์ข
(doorbell) ์ ์ฌ์ฉํด ์
๋ฐ์ดํธ๋ ๋์คํฌ๋ฆฝํฐ๊ฐ ๋๋ฐ์ด์ค์ ์ฌ์ฉ
๊ฐ๋ฅํด์ก์์ ๊ณต์งํ๋ ๋๋ฐ์ด์ค ๋๋ผ์ด๋ฒ๋ฅผ ์๊ฐํด ๋ด
์๋ค:
if (desc->status != DEVICE_OWN) {
/* ๋์คํฌ๋ฆฝํฐ๋ฅผ ์์ ํ๊ธฐ ์ ์๋ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ง ์์ */
dma_rmb();
/* ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ณ ์ */
read_data = desc->data;
desc->data = write_data;
/* ์ํ ์
๋ฐ์ดํธ ์ ์์ ์ฌํญ์ ๋ฐ์ */
dma_wmb();
/* ์์ ๊ถ์ ์์ */
desc->status = DEVICE_OWN;
/* MMIO ๋ฅผ ํตํด ๋๋ฐ์ด์ค์ ๊ณต์ง๋ฅผ ํ๊ธฐ ์ ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋๊ธฐํ */
wmb();
/* ์
๋ฐ์ดํธ๋ ๋์คํฌ๋ฆฝํฐ์ ๋๋ฐ์ด์ค์ ๊ณต์ง */
writel(DESC_NOTIFY, doorbell);
}
dma_rmb() ๋ ๋์คํฌ๋ฆฝํฐ๋ก๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด์ค๊ธฐ ์ ์ ๋๋ฐ์ด์ค๊ฐ ์์ ๊ถ์
๋ด๋์์์ ๋ณด์ฅํ๊ฒ ํ๊ณ , dma_wmb() ๋ ๋๋ฐ์ด์ค๊ฐ ์์ ์ด ์์ ๊ถ์ ๋ค์
๊ฐ์ก์์ ๋ณด๊ธฐ ์ ์ ๋์คํฌ๋ฆฝํฐ์ ๋ฐ์ดํฐ๊ฐ ์ฐ์์์ ๋ณด์ฅํฉ๋๋ค. wmb() ๋
์บ์ ์ผ๊ด์ฑ์ด ์๋ (cache incoherent) MMIO ์์ญ์ ์ฐ๊ธฐ๋ฅผ ์๋ํ๊ธฐ ์ ์
์บ์ ์ผ๊ด์ฑ์ด ์๋ ๋ฉ๋ชจ๋ฆฌ (cache coherent memory) ์ฐ๊ธฐ๊ฐ ์๋ฃ๋์์์
๋ณด์ฅํด์ฃผ๊ธฐ ์ํด ํ์ํฉ๋๋ค.
consistent memory ์ ๋ํ ์์ธํ ๋ด์ฉ์ ์ํด์ Documentation/DMA-API.txt
๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์ธ์.
MMIO ์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด
----------------
๋ฆฌ๋
์ค ์ปค๋์ ๋ํ memory-mapped I/O ์ฐ๊ธฐ๋ฅผ ์ํ ํน๋ณํ ๋ฐฐ๋ฆฌ์ด๋ ๊ฐ์ง๊ณ
์์ต๋๋ค:
mmiowb();
์ด๊ฒ์ mandatory ์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด์ ๋ณ์ข
์ผ๋ก, ์ํ๋ ์์ ๊ท์น์ I/O ์์ญ์์ผ๋ก์
์ฐ๊ธฐ๊ฐ ๋ถ๋ถ์ ์ผ๋ก ์์๋ฅผ ๋ง์ถ๋๋ก ํด์ค๋๋ค. ์ด ํจ์๋ CPU->ํ๋์จ์ด ์ฌ์ด๋ฅผ
๋์ด์ ์ค์ ํ๋์จ์ด์๊น์ง ์ผ๋ถ ์์ค์ ์ํฅ์ ๋ผ์นฉ๋๋ค.
๋ ๋ง์ ์ ๋ณด๋ฅผ ์ํด์ "Acquire vs I/O ์ก์ธ์ค" ์๋ธ์น์
์ ์ฐธ๊ณ ํ์ธ์.
=========================
์๋ฌต์ ์ปค๋ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด
=========================
๋ฆฌ๋
์ค ์ปค๋์ ์ผ๋ถ ํจ์๋ค์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ ๋ด์ฅํ๊ณ ์๋๋ฐ, ๋ฝ(lock)๊ณผ
์ค์ผ์ฅด๋ง ๊ด๋ จ ํจ์๋ค์ด ๋๋ถ๋ถ์
๋๋ค.
์ฌ๊ธฐ์ _์ต์ํ์_ ๋ณด์ฅ์ ์ค๋ช
ํฉ๋๋ค; ํน์ ์ํคํ
์ณ์์๋ ์ด ์ค๋ช
๋ณด๋ค ๋ ๋ง์
๋ณด์ฅ์ ์ ๊ณตํ ์๋ ์์ต๋๋ค๋ง ํด๋น ์ํคํ
์ณ์ ์ข
์์ ์ธ ์ฝ๋ ์ธ์ ๋ถ๋ถ์์๋
๊ทธ๋ฐ ๋ณด์ฅ์ ๊ธฐ๋ํด์ ์๋ ๊ฒ๋๋ค.
๋ฝ ACQUISITION ํจ์
-------------------
๋ฆฌ๋
์ค ์ปค๋์ ๋ค์ํ ๋ฝ ๊ตฌ์ฑ์ฒด๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค:
(*) ์คํ ๋ฝ
(*) R/W ์คํ ๋ฝ
(*) ๋ฎคํ
์ค
(*) ์ธ๋งํฌ์ด
(*) R/W ์ธ๋งํฌ์ด
๊ฐ ๊ตฌ์ฑ์ฒด๋ง๋ค ๋ชจ๋ ๊ฒฝ์ฐ์ "ACQUIRE" ์คํผ๋ ์ด์
๊ณผ "RELEASE" ์คํผ๋ ์ด์
์ ๋ณ์ข
์ด
์กด์ฌํฉ๋๋ค. ์ด ์คํผ๋ ์ด์
๋ค์ ๋ชจ๋ ์ ์ ํ ๋ฐฐ๋ฆฌ์ด๋ฅผ ๋ดํฌํ๊ณ ์์ต๋๋ค:
(1) ACQUIRE ์คํผ๋ ์ด์
์ ์ํฅ:
ACQUIRE ๋ค์์ ์์ฒญ๋ ๋ฉ๋ชจ๋ฆฌ ์คํผ๋ ์ด์
์ ACQUIRE ์คํผ๋ ์ด์
์ด ์๋ฃ๋
๋ค์ ์๋ฃ๋ฉ๋๋ค.
ACQUIRE ์์์ ์์ฒญ๋ ๋ฉ๋ชจ๋ฆฌ ์คํผ๋ ์ด์
์ ACQUIRE ์คํผ๋ ์ด์
์ด ์๋ฃ๋ ํ์
์๋ฃ๋ ์ ์์ต๋๋ค. smp_mb__before_spinlock() ๋ค์ ACQUIRE ๊ฐ ์คํ๋๋
์ฝ๋ ๋ธ๋ก์ ๋ธ๋ก ์์ ์คํ ์ด๋ฅผ ๋ธ๋ก ๋ค์ ๋ก๋์ ์คํ ์ด์ ๋ํด ์์
๋ง์ถฅ๋๋ค. ์ด๊ฑด smp_mb() ๋ณด๋ค ์ํ๋ ๊ฒ์์ ๊ธฐ์ตํ์ธ์! ๋ง์ ์ํคํ
์ณ์์
smp_mb__before_spinlock() ์ ์ฌ์ค ์๋ฌด์ผ๋ ํ์ง ์์ต๋๋ค.
(2) RELEASE ์คํผ๋ ์ด์
์ ์ํฅ:
RELEASE ์์์ ์์ฒญ๋ ๋ฉ๋ชจ๋ฆฌ ์คํผ๋ ์ด์
์ RELEASE ์คํผ๋ ์ด์
์ด ์๋ฃ๋๊ธฐ
์ ์ ์๋ฃ๋ฉ๋๋ค.
RELEASE ๋ค์์ ์์ฒญ๋ ๋ฉ๋ชจ๋ฆฌ ์คํผ๋ ์ด์
์ RELEASE ์คํผ๋ ์ด์
์๋ฃ ์ ์
์๋ฃ๋ ์ ์์ต๋๋ค.
(3) ACQUIRE vs ACQUIRE ์ํฅ:
์ด๋ค ACQUIRE ์คํผ๋ ์ด์
๋ณด๋ค ์์์ ์์ฒญ๋ ๋ชจ๋ ACQUIRE ์คํผ๋ ์ด์
์ ๊ทธ
ACQUIRE ์คํผ๋ ์ด์
์ ์ ์๋ฃ๋ฉ๋๋ค.
(4) ACQUIRE vs RELEASE implication:
์ด๋ค RELEASE ์คํผ๋ ์ด์
๋ณด๋ค ์์ ์์ฒญ๋ ACQUIRE ์คํผ๋ ์ด์
์ ๊ทธ RELEASE
์คํผ๋ ์ด์
๋ณด๋ค ๋จผ์ ์๋ฃ๋ฉ๋๋ค.
(5) ์คํจํ ์กฐ๊ฑด์ ACQUIRE ์ํฅ:
ACQUIRE ์คํผ๋ ์ด์
์ ์ผ๋ถ ๋ฝ(lock) ๋ณ์ข
์ ๋ฝ์ด ๊ณง๋ฐ๋ก ํ๋ํ๊ธฐ์๋
๋ถ๊ฐ๋ฅํ ์ํ์ด๊ฑฐ๋ ๋ฝ์ด ํ๋ ๊ฐ๋ฅํด์ง๋๋ก ๊ธฐ๋ค๋ฆฌ๋ ๋์ค ์๊ทธ๋์ ๋ฐ๊ฑฐ๋
ํด์ ์คํจํ ์ ์์ต๋๋ค. ์คํจํ ๋ฝ์ ์ด๋ค ๋ฐฐ๋ฆฌ์ด๋ ๋ดํฌํ์ง ์์ต๋๋ค.
[!] ์ฐธ๊ณ : ๋ฝ ACQUIRE ์ RELEASE ๊ฐ ๋จ๋ฐฉํฅ ๋ฐฐ๋ฆฌ์ด์ฌ์ ๋ํ๋๋ ํ์ ์ค ํ๋๋
ํฌ๋ฆฌํฐ์ปฌ ์น์
๋ฐ๊นฅ์ ์ธ์คํธ๋ญ์
์ ์ํฅ์ด ํฌ๋ฆฌํฐ์ปฌ ์น์
๋ด๋ถ๋ก๋ ๋ค์ด์ฌ ์
์๋ค๋ ๊ฒ์
๋๋ค.
RELEASE ํ์ ์์ฒญ๋๋ ACQUIRE ๋ ์ ์ฒด ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ผ ์ฌ๊ฒจ์ง๋ฉด ์๋๋๋ฐ,
ACQUIRE ์์ ์ก์ธ์ค๊ฐ ACQUIRE ํ์ ์ํ๋ ์ ์๊ณ , RELEASE ํ์ ์ก์ธ์ค๊ฐ
RELEASE ์ ์ ์ํ๋ ์๋ ์์ผ๋ฉฐ, ๊ทธ ๋๊ฐ์ ์ก์ธ์ค๊ฐ ์๋ก๋ฅผ ์ง๋์น ์๋ ์๊ธฐ
๋๋ฌธ์
๋๋ค:
*A = a;
ACQUIRE M
RELEASE M
*B = b;
๋ ๋ค์๊ณผ ๊ฐ์ด ๋ ์๋ ์์ต๋๋ค:
ACQUIRE M, STORE *B, STORE *A, RELEASE M
ACQUIRE ์ RELEASE ๊ฐ ๋ฝ ํ๋๊ณผ ํด์ ๋ผ๋ฉด, ๊ทธ๋ฆฌ๊ณ ๋ฝ์ ACQUIRE ์ RELEASE ๊ฐ
๊ฐ์ ๋ฝ ๋ณ์์ ๋ํ ๊ฒ์ด๋ผ๋ฉด, ํด๋น ๋ฝ์ ์ฅ๊ณ ์์ง ์์ ๋ค๋ฅธ CPU ์ ์์ผ์๋
์ด์ ๊ฐ์ ์ฌ๋ฐฐ์น๊ฐ ์ผ์ด๋๋ ๊ฒ์ผ๋ก ๋ณด์ผ ์ ์์ต๋๋ค. ์์ฝํ์๋ฉด, ACQUIRE ์
์ด์ด RELEASE ์คํผ๋ ์ด์
์ ์์ฐจ์ ์ผ๋ก ์คํํ๋ ํ์๊ฐ ์ ์ฒด ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ก
์๊ฐ๋์ด์ -์๋ฉ๋๋ค-.
๋น์ทํ๊ฒ, ์์ ๋ฐ๋ ์ผ์ด์ค์ธ RELEASE ์ ACQUIRE ๋๊ฐ ์คํผ๋ ์ด์
์ ์์ฐจ์ ์คํ
์ญ์ ์ ์ฒด ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ ๋ดํฌํ์ง ์์ต๋๋ค. ๋ฐ๋ผ์, RELEASE, ACQUIRE ๋ก
๊ท์ ๋๋ ํฌ๋ฆฌํฐ์ปฌ ์น์
์ CPU ์ํ์ RELEASE ์ ACQUIRE ๋ฅผ ๊ฐ๋ก์ง๋ฅผ ์ ์์ผ๋ฏ๋ก,
๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋:
*A = a;
RELEASE M
ACQUIRE N
*B = b;
๋ค์๊ณผ ๊ฐ์ด ์ํ๋ ์ ์์ต๋๋ค:
ACQUIRE N, STORE *B, STORE *A, RELEASE M
์ด๋ฐ ์ฌ๋ฐฐ์น๋ ๋ฐ๋๋ฝ์ ์ผ์ผํฌ ์๋ ์์ ๊ฒ์ฒ๋ผ ๋ณด์ผ ์ ์์ต๋๋ค. ํ์ง๋ง, ๊ทธ๋ฐ
๋ฐ๋๋ฝ์ ์กฐ์ง์ด ์๋ค๋ฉด RELEASE ๋ ๋จ์ํ ์๋ฃ๋ ๊ฒ์ด๋ฏ๋ก ๋ฐ๋๋ฝ์ ์กด์ฌํ ์
์์ต๋๋ค.
์ด๊ฒ ์ด๋ป๊ฒ ์ฌ๋ฐ๋ฅธ ๋์์ ํ ์ ์์๊น์?
์ฐ๋ฆฌ๊ฐ ์ด์ผ๊ธฐ ํ๊ณ ์๋๊ฑด ์ฌ๋ฐฐ์น๋ฅผ ํ๋ CPU ์ ๋ํ ์ด์ผ๊ธฐ์ด์ง,
์ปดํ์ผ๋ฌ์ ๋ํ ๊ฒ์ด ์๋๋ ์ ์ด ํต์ฌ์
๋๋ค. ์ปดํ์ผ๋ฌ (๋๋, ๊ฐ๋ฐ์)
๊ฐ ์คํผ๋ ์ด์
๋ค์ ์ด๋ ๊ฒ ์ฌ๋ฐฐ์นํ๋ฉด, ๋ฐ๋๋ฝ์ด ์ผ์ด๋ ์ -์์ต-๋๋ค.
ํ์ง๋ง CPU ๊ฐ ์คํผ๋ ์ด์
๋ค์ ์ฌ๋ฐฐ์น ํ๋ค๋๊ฑธ ์๊ฐํด ๋ณด์ธ์. ์ด ์์์,
์ด์
๋ธ๋ฆฌ ์ฝ๋ ์์ผ๋ก๋ ์ธ๋ฝ์ด ๋ฝ์ ์์๊ฒ ๋์ด ์์ต๋๋ค. CPU ๊ฐ ์ด๋ฅผ
์ฌ๋ฐฐ์นํด์ ๋ค์ ๋ฝ ์คํผ๋ ์ด์
์ ๋จผ์ ์คํํ๊ฒ ๋ฉ๋๋ค. ๋ง์ฝ ๋ฐ๋๋ฝ์ด
์กด์ฌํ๋ค๋ฉด, ์ด ๋ฝ ์คํผ๋ ์ด์
์ ๊ทธ์ ์คํ์ ํ๋ฉฐ ๊ณ์ํด์ ๋ฝ์
์๋ํฉ๋๋ค (๋๋, ํ์ฐธ ํ์๊ฒ ์ง๋ง, ์ ๋ญ๋๋ค). CPU ๋ ์ธ์ ๊ฐ๋
(์ด์
๋ธ๋ฆฌ ์ฝ๋์์๋ ๋ฝ์ ์์๋) ์ธ๋ฝ ์คํผ๋ ์ด์
์ ์คํํ๋๋ฐ, ์ด ์ธ๋ฝ
์คํผ๋ ์ด์
์ด ์ ์ฌ์ ๋ฐ๋๋ฝ์ ํด๊ฒฐํ๊ณ , ๋ฝ ์คํผ๋ ์ด์
๋ ๋ค์ด์ด ์ฑ๊ณตํ๊ฒ
๋ฉ๋๋ค.
ํ์ง๋ง ๋ง์ฝ ๋ฝ์ด ์ ์ ์๋ ํ์
์ด์๋ค๋ฉด์? ๊ทธ๋ฐ ๊ฒฝ์ฐ์ ์ฝ๋๋
์ค์ผ์ฅด๋ฌ๋ก ๋ค์ด๊ฐ๋ ค ํ ๊ฑฐ๊ณ , ์ฌ๊ธฐ์ ๊ฒฐ๊ตญ์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ ๋ง๋๊ฒ
๋๋๋ฐ, ์ด ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ ์์ ์ธ๋ฝ ์คํผ๋ ์ด์
์ด ์๋ฃ๋๋๋ก ๋ง๋ค๊ณ ,
๋ฐ๋๋ฝ์ ์ด๋ฒ์๋ ํด๊ฒฐ๋ฉ๋๋ค. ์ ์ ์๋ ํ์์ ์ธ๋ฝ ์ฌ์ด์ ๊ฒฝ์ฃผ ์ํฉ
(race) ๋ ์์ ์ ์๊ฒ ์ต๋๋ค๋ง, ๋ฝ ๊ด๋ จ ๊ธฐ๋ฅ๋ค์ ๊ทธ๋ฐ ๊ฒฝ์ฃผ ์ํฉ์ ๋ชจ๋
๊ฒฝ์ฐ์ ์ ๋๋ก ํด๊ฒฐํ ์ ์์ด์ผ ํฉ๋๋ค.
๋ฝ๊ณผ ์ธ๋งํฌ์ด๋ UP ์ปดํ์ผ๋ ์์คํ
์์์ ์์์ ๋ํด ๋ณด์ฅ์ ํ์ง ์๊ธฐ ๋๋ฌธ์,
๊ทธ๋ฐ ์ํฉ์์ ์ธํฐ๋ฝํธ ๋นํ์ฑํ ์คํผ๋ ์ด์
๊ณผ ํจ๊ป๊ฐ ์๋๋ผ๋ฉด ์ด๋ค ์ผ์๋ - ํนํ
I/O ์ก์ธ์ค์ ๊ด๋ จํด์๋ - ์ ๋๋ก ์ฌ์ฉ๋ ์ ์์ ๊ฒ๋๋ค.
"CPU ๊ฐ ACQUIRING ๋ฐฐ๋ฆฌ์ด ํจ๊ณผ" ์น์
๋ ์ฐธ๊ณ ํ์๊ธฐ ๋ฐ๋๋๋ค.
์๋ฅผ ๋ค์ด, ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ฅผ ์๊ฐํด ๋ด
์๋ค:
*A = a;
*B = b;
ACQUIRE
*C = c;
*D = d;
RELEASE
*E = e;
*F = f;
์ฌ๊ธฐ์ ๋ค์์ ์ด๋ฒคํธ ์ํ์ค๊ฐ ์๊ธธ ์ ์์ต๋๋ค:
ACQUIRE, {*F,*A}, *E, {*C,*D}, *B, RELEASE
[+] {*F,*A} ๋ ์กฐํฉ๋ ์ก์ธ์ค๋ฅผ ์๋ฏธํฉ๋๋ค.
ํ์ง๋ง ๋ค์๊ณผ ๊ฐ์ ๊ฑด ๋ถ๊ฐ๋ฅํ์ฃ :
{*F,*A}, *B, ACQUIRE, *C, *D, RELEASE, *E
*A, *B, *C, ACQUIRE, *D, RELEASE, *E, *F
*A, *B, ACQUIRE, *C, RELEASE, *D, *E, *F
*B, ACQUIRE, *C, *D, RELEASE, {*F,*A}, *E
์ธํฐ๋ฝํธ ๋นํ์ฑํ ํจ์
----------------------
์ธํฐ๋ฝํธ๋ฅผ ๋นํ์ฑํ ํ๋ ํจ์ (ACQUIRE ์ ๋์ผ) ์ ์ธํฐ๋ฝํธ๋ฅผ ํ์ฑํ ํ๋ ํจ์
(RELEASE ์ ๋์ผ) ๋ ์ปดํ์ผ๋ฌ ๋ฐฐ๋ฆฌ์ด์ฒ๋ผ๋ง ๋์ํฉ๋๋ค. ๋ฐ๋ผ์, ๋ณ๋์ ๋ฉ๋ชจ๋ฆฌ
๋ฐฐ๋ฆฌ์ด๋ I/O ๋ฐฐ๋ฆฌ์ด๊ฐ ํ์ํ ์ํฉ์ด๋ผ๋ฉด ๊ทธ ๋ฐฐ๋ฆฌ์ด๋ค์ ์ธํฐ๋ฝํธ ๋นํ์ฑํ ํจ์
์ธ์ ๋ฐฉ๋ฒ์ผ๋ก ์ ๊ณต๋์ด์ผ๋ง ํฉ๋๋ค.
์ฌ๋ฆฝ๊ณผ ์จ์ดํฌ์
ํจ์
--------------------
๊ธ๋ก๋ฒ ๋ฐ์ดํฐ์ ํ์๋ ์ด๋ฒคํธ์ ์ํด ํ๋ก์ธ์ค๋ฅผ ์ ์ ๋น ํธ๋ฆฌ๋ ๊ฒ๊ณผ ๊นจ์ฐ๋ ๊ฒ์
ํด๋น ์ด๋ฒคํธ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ํ์คํฌ์ ํ์คํฌ ์ํ์ ๊ทธ ์ด๋ฒคํธ๋ฅผ ์๋ฆฌ๊ธฐ ์ํด ์ฌ์ฉ๋๋
๊ธ๋ก๋ฒ ๋ฐ์ดํฐ, ๋ ๋ฐ์ดํฐ๊ฐ์ ์ํธ์์ฉ์ผ๋ก ๋ณผ ์ ์์ต๋๋ค. ์ด๊ฒ์ด ์ณ์ ์์๋๋ก
์ผ์ด๋จ์ ๋ถ๋ช
ํ ํ๊ธฐ ์ํด, ํ๋ก์ธ์ค๋ฅผ ์ ์ ๋ค๊ฒ ํ๋ ๊ธฐ๋ฅ๊ณผ ๊นจ์ฐ๋ ๊ธฐ๋ฅ์
๋ช๊ฐ์ง ๋ฐฐ๋ฆฌ์ด๋ฅผ ๋ดํฌํฉ๋๋ค.
๋จผ์ , ์ ์ ์ฌ์ฐ๋ ์ชฝ์ ์ผ๋ฐ์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ ์ด๋ฒคํธ ์ํ์ค๋ฅผ ๋ฐ๋ฆ
๋๋ค:
for (;;) {
set_current_state(TASK_UNINTERRUPTIBLE);
if (event_indicated)
break;
schedule();
}
set_current_state() ์ ์ํด, ํ์คํฌ ์ํ๊ฐ ๋ฐ๋ ํ ๋ฒ์ฉ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๊ฐ
์๋์ผ๋ก ์ฝ์
๋ฉ๋๋ค:
CPU 1
===============================
set_current_state();
smp_store_mb();
STORE current->state
<๋ฒ์ฉ ๋ฐฐ๋ฆฌ์ด>
LOAD event_indicated
set_current_state() ๋ ๋ค์์ ๊ฒ๋ค๋ก ๊ฐ์ธ์ง ์๋ ์์ต๋๋ค:
prepare_to_wait();
prepare_to_wait_exclusive();
์ด๊ฒ๋ค ์ญ์ ์ํ๋ฅผ ์ค์ ํ ํ ๋ฒ์ฉ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ ์ฝ์
ํฉ๋๋ค.
์์ ์ ์ฒด ์ํ์ค๋ ๋ค์๊ณผ ๊ฐ์ ํจ์๋ค๋ก ํ๋ฒ์ ์ํ ๊ฐ๋ฅํ๋ฐ, ์ด๊ฒ๋ค์ ๋ชจ๋
์ฌ๋ฐ๋ฅธ ์ฅ์์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ ์ฝ์
ํฉ๋๋ค:
wait_event();
wait_event_interruptible();
wait_event_interruptible_exclusive();
wait_event_interruptible_timeout();
wait_event_killable();
wait_event_timeout();
wait_on_bit();
wait_on_bit_lock();
๋๋ฒ์งธ๋ก, ๊นจ์ฐ๊ธฐ๋ฅผ ์ํํ๋ ์ฝ๋๋ ์ผ๋ฐ์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ ๊ฒ๋๋ค:
event_indicated = 1;
wake_up(&event_wait_queue);
๋๋:
event_indicated = 1;
wake_up_process(event_daemon);
wake_up() ๋ฅ์ ์ํด ์ฐ๊ธฐ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๊ฐ ๋ดํฌ๋ฉ๋๋ค. ๋ง์ฝ ๊ทธ๊ฒ๋ค์ด ๋ญ๊ฐ๋ฅผ
๊นจ์ด๋ค๋ฉด์. ์ด ๋ฐฐ๋ฆฌ์ด๋ ํ์คํฌ ์ํ๊ฐ ์ง์์ง๊ธฐ ์ ์ ์ํ๋๋ฏ๋ก, ์ด๋ฒคํธ๋ฅผ
์๋ฆฌ๊ธฐ ์ํ STORE ์ ํ์คํฌ ์ํ๋ฅผ TASK_RUNNING ์ผ๋ก ์ค์ ํ๋ STORE ์ฌ์ด์
์์นํ๊ฒ ๋ฉ๋๋ค.
CPU 1 CPU 2
=============================== ===============================
set_current_state(); STORE event_indicated
smp_store_mb(); wake_up();
STORE current->state <์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด>
<๋ฒ์ฉ ๋ฐฐ๋ฆฌ์ด> STORE current->state
LOAD event_indicated
ํ๋ฒ๋ ๋งํฉ๋๋ค๋ง, ์ด ์ฐ๊ธฐ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ ์ด ์ฝ๋๊ฐ ์ ๋ง๋ก ๋ญ๊ฐ๋ฅผ ๊นจ์ธ ๋์๋ง
์คํ๋ฉ๋๋ค. ์ด๊ฑธ ์ค๋ช
ํ๊ธฐ ์ํด, X ์ Y ๋ ๋ชจ๋ 0 ์ผ๋ก ์ด๊ธฐํ ๋์ด ์๋ค๋ ๊ฐ์
ํ์ ์๋์ ์ด๋ฒคํธ ์ํ์ค๋ฅผ ์๊ฐํด ๋ด
์๋ค:
CPU 1 CPU 2
=============================== ===============================
X = 1; STORE event_indicated
smp_mb(); wake_up();
Y = 1; wait_event(wq, Y == 1);
wake_up(); load from Y sees 1, no memory barrier
load from X might see 0
์ ์์ ์์์ ๊ฒฝ์ฐ์ ๋ฌ๋ฆฌ ๊นจ์ฐ๊ธฐ๊ฐ ์ ๋ง๋ก ํํด์ก๋ค๋ฉด, CPU 2 ์ X ๋ก๋๋ 1 ์
๋ณธ๋ค๊ณ ๋ณด์ฅ๋ ์ ์์ ๊ฒ๋๋ค.
์ฌ์ฉ ๊ฐ๋ฅํ ๊นจ์ฐ๊ธฐ๋ฅ ํจ์๋ค๋ก ๋ค์๊ณผ ๊ฐ์ ๊ฒ๋ค์ด ์์ต๋๋ค:
complete();
wake_up();
wake_up_all();
wake_up_bit();
wake_up_interruptible();
wake_up_interruptible_all();
wake_up_interruptible_nr();
wake_up_interruptible_poll();
wake_up_interruptible_sync();
wake_up_interruptible_sync_poll();
wake_up_locked();
wake_up_locked_poll();
wake_up_nr();
wake_up_poll();
wake_up_process();
[!] ์ ์ฌ์ฐ๋ ์ฝ๋์ ๊นจ์ฐ๋ ์ฝ๋์ ๋ดํฌ๋๋ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ค์ ๊นจ์ฐ๊ธฐ ์ ์
์ด๋ฃจ์ด์ง ์คํ ์ด๋ฅผ ์ ์ฌ์ฐ๋ ์ฝ๋๊ฐ set_current_state() ๋ฅผ ํธ์ถํ ํ์ ํํ๋
๋ก๋์ ๋ํด ์์๋ฅผ ๋ง์ถ์ง _์๋๋ค๋_ ์ ์ ๊ธฐ์ตํ์ธ์. ์๋ฅผ ๋ค์ด, ์ ์ฌ์ฐ๋
์ฝ๋๊ฐ ๋ค์๊ณผ ๊ฐ๊ณ :
set_current_state(TASK_INTERRUPTIBLE);
if (event_indicated)
break;
__set_current_state(TASK_RUNNING);
do_something(my_data);
๊นจ์ฐ๋ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ๋ค๋ฉด:
my_data = value;
event_indicated = 1;
wake_up(&event_wait_queue);
event_indecated ์์ ๋ณ๊ฒฝ์ด ์ ์ฌ์ฐ๋ ์ฝ๋์๊ฒ my_data ์์ ๋ณ๊ฒฝ ํ์ ์ด๋ฃจ์ด์ง
๊ฒ์ผ๋ก ์ธ์ง๋ ๊ฒ์ด๋ผ๋ ๋ณด์ฅ์ด ์์ต๋๋ค. ์ด๋ฐ ๊ฒฝ์ฐ์๋ ์์ชฝ ์ฝ๋ ๋ชจ๋ ๊ฐ๊ฐ์
๋ฐ์ดํฐ ์ก์ธ์ค ์ฌ์ด์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ ์ง์ ์ณ์ผ ํฉ๋๋ค. ๋ฐ๋ผ์ ์์ ์ฌ์ฐ๋
์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ด:
set_current_state(TASK_INTERRUPTIBLE);
if (event_indicated) {
smp_rmb();
do_something(my_data);
}
๊ทธ๋ฆฌ๊ณ ๊นจ์ฐ๋ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ด ๋์ด์ผ ํฉ๋๋ค:
my_data = value;
smp_wmb();
event_indicated = 1;
wake_up(&event_wait_queue);
๊ทธ์ธ์ ํจ์๋ค
-------------
๊ทธ์ธ์ ๋ฐฐ๋ฆฌ์ด๋ฅผ ๋ดํฌํ๋ ํจ์๋ค์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
(*) schedule() ๊ณผ ๊ทธ ์ ์ฌํ ๊ฒ๋ค์ด ์์ ํ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ ๋ดํฌํฉ๋๋ค.
==============================
CPU ๊ฐ ACQUIRING ๋ฐฐ๋ฆฌ์ด์ ํจ๊ณผ
==============================
SMP ์์คํ
์์์ ๋ฝ ๊ธฐ๋ฅ๋ค์ ๋์ฑ ๊ฐ๋ ฅํ ํํ์ ๋ฐฐ๋ฆฌ์ด๋ฅผ ์ ๊ณตํฉ๋๋ค: ์ด
๋ฐฐ๋ฆฌ์ด๋ ๋์ผํ ๋ฝ์ ์ฌ์ฉํ๋ ๋ค๋ฅธ CPU ๋ค์ ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค ์์์๋ ์ํฅ์
๋ผ์นฉ๋๋ค.
ACQUIRE VS ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค
------------------------
๋ค์์ ์๋ฅผ ์๊ฐํด ๋ด
์๋ค: ์์คํ
์ ๋๊ฐ์ ์คํ๋ฝ (M) ๊ณผ (Q), ๊ทธ๋ฆฌ๊ณ ์ธ๊ฐ์ CPU
๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค; ์ฌ๊ธฐ์ ๋ค์์ ์ด๋ฒคํธ ์ํ์ค๊ฐ ๋ฐ์ํฉ๋๋ค:
CPU 1 CPU 2
=============================== ===============================
WRITE_ONCE(*A, a); WRITE_ONCE(*E, e);
ACQUIRE M ACQUIRE Q
WRITE_ONCE(*B, b); WRITE_ONCE(*F, f);
WRITE_ONCE(*C, c); WRITE_ONCE(*G, g);
RELEASE M RELEASE Q
WRITE_ONCE(*D, d); WRITE_ONCE(*H, h);
*A ๋ก์ ์ก์ธ์ค๋ถํฐ *H ๋ก์ ์ก์ธ์ค๊น์ง๊ฐ ์ด๋ค ์์๋ก CPU 3 ์๊ฒ ๋ณด์ฌ์ง์ง์
๋ํด์๋ ๊ฐ CPU ์์์ ๋ฝ ์ฌ์ฉ์ ์ํด ๋ดํฌ๋์ด ์๋ ์ ์ฝ์ ์ ์ธํ๊ณ ๋ ์ด๋ค
๋ณด์ฅ๋ ์กด์ฌํ์ง ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, CPU 3 ์๊ฒ ๋ค์๊ณผ ๊ฐ์ ์์๋ก ๋ณด์ฌ์ง๋
๊ฒ์ด ๊ฐ๋ฅํฉ๋๋ค:
*E, ACQUIRE M, ACQUIRE Q, *G, *C, *F, *A, *B, RELEASE Q, *D, *H, RELEASE M
ํ์ง๋ง ๋ค์๊ณผ ๊ฐ์ด ๋ณด์ด์ง๋ ์์ ๊ฒ๋๋ค:
*B, *C or *D preceding ACQUIRE M
*A, *B or *C following RELEASE M
*F, *G or *H preceding ACQUIRE Q
*E, *F or *G following RELEASE Q
ACQUIRE VS I/O ์ก์ธ์ค
----------------------
ํน์ ํ (ํนํ NUMA ๊ฐ ๊ด๋ จ๋) ํ๊ฒฝ ํ์์ ๋๊ฐ์ CPU ์์ ๋์ผํ ์คํ๋ฝ์ผ๋ก
๋ณดํธ๋๋ ๋๊ฐ์ ํฌ๋ฆฌํฐ์ปฌ ์น์
์์ I/O ์ก์ธ์ค๋ PCI ๋ธ๋ฆฟ์ง์ ๊ฒน์ณ์ง I/O
์ก์ธ์ค๋ก ๋ณด์ผ ์ ์๋๋ฐ, PCI ๋ธ๋ฆฟ์ง๋ ์บ์ ์ผ๊ด์ฑ ํ๋กํ ์ฝ๊ณผ ํฉ์ ๋ง์ถฐ์ผ ํ
์๋ฌด๊ฐ ์์ผ๋ฏ๋ก, ํ์ํ ์ฝ๊ธฐ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๊ฐ ์์ฒญ๋์ง ์๊ธฐ ๋๋ฌธ์
๋๋ค.
์๋ฅผ ๋ค์ด์:
CPU 1 CPU 2
=============================== ===============================
spin_lock(Q)
writel(0, ADDR)
writel(1, DATA);
spin_unlock(Q);
spin_lock(Q);
writel(4, ADDR);
writel(5, DATA);
spin_unlock(Q);
๋ PCI ๋ธ๋ฆฟ์ง์ ๋ค์๊ณผ ๊ฐ์ด ๋ณด์ผ ์ ์์ต๋๋ค:
STORE *ADDR = 0, STORE *ADDR = 4, STORE *DATA = 1, STORE *DATA = 5
์ด๋ ๊ฒ ๋๋ฉด ํ๋์จ์ด์ ์ค๋์์ ์ผ์ผํฌ ์ ์์ต๋๋ค.
์ด๋ฐ ๊ฒฝ์ฐ์ ์ก์๋ ์คํ๋ฝ์ ๋ด๋ ค๋๊ธฐ ์ ์ mmiowb() ๋ฅผ ์ํํด์ผ ํ๋๋ฐ, ์๋ฅผ
๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
CPU 1 CPU 2
=============================== ===============================
spin_lock(Q)
writel(0, ADDR)
writel(1, DATA);
mmiowb();
spin_unlock(Q);
spin_lock(Q);
writel(4, ADDR);
writel(5, DATA);
mmiowb();
spin_unlock(Q);
์ด ์ฝ๋๋ CPU 1 ์์ ์์ฒญ๋ ๋๊ฐ์ ์คํ ์ด๊ฐ PCI ๋ธ๋ฆฟ์ง์ CPU 2 ์์ ์์ฒญ๋
์คํ ์ด๋ค๋ณด๋ค ๋จผ์ ๋ณด์ฌ์ง์ ๋ณด์ฅํฉ๋๋ค.
๋ํ, ๊ฐ์ ๋๋ฐ์ด์ค์์ ์คํ ์ด๋ฅผ ์ด์ด ๋ก๋๊ฐ ์ํ๋๋ฉด ์ด ๋ก๋๋ ๋ก๋๊ฐ ์ํ๋๊ธฐ
์ ์ ์คํ ์ด๊ฐ ์๋ฃ๋๊ธฐ๋ฅผ ๊ฐ์ ํ๋ฏ๋ก mmiowb() ์ ํ์๊ฐ ์์ด์ง๋๋ค:
CPU 1 CPU 2
=============================== ===============================
spin_lock(Q)
writel(0, ADDR)
a = readl(DATA);
spin_unlock(Q);
spin_lock(Q);
writel(4, ADDR);
b = readl(DATA);
spin_unlock(Q);
๋ ๋ง์ ์ ๋ณด๋ฅผ ์ํด์ Documenataion/DocBook/deviceiobook.tmpl ์ ์ฐธ๊ณ ํ์ธ์.
=========================
๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๊ฐ ํ์ํ ๊ณณ
=========================
์ค๋ น SMP ์ปค๋์ ์ฌ์ฉํ๋๋ผ๋ ์ฑ๊ธ ์ฐ๋ ๋๋ก ๋์ํ๋ ์ฝ๋๋ ์ฌ๋ฐ๋ฅด๊ฒ ๋์ํ๋
๊ฒ์ผ๋ก ๋ณด์ฌ์ง ๊ฒ์ด๊ธฐ ๋๋ฌธ์, ํ๋ฒํ ์์คํ
์ด์์ค์ ๋ฉ๋ชจ๋ฆฌ ์คํผ๋ ์ด์
์ฌ๋ฐฐ์น๋
์ผ๋ฐ์ ์ผ๋ก ๋ฌธ์ ๊ฐ ๋์ง ์์ต๋๋ค. ํ์ง๋ง, ์ฌ๋ฐฐ์น๊ฐ ๋ฌธ์ ๊ฐ _๋ ์ ์๋_ ๋ค๊ฐ์ง
ํ๊ฒฝ์ด ์์ต๋๋ค:
(*) ํ๋ก์ธ์๊ฐ ์ํธ ์์ฉ.
(*) ์ดํ ๋ฏน ์คํผ๋ ์ด์
.
(*) ๋๋ฐ์ด์ค ์ก์ธ์ค.
(*) ์ธํฐ๋ฝํธ.
ํ๋ก์ธ์๊ฐ ์ํธ ์์ฉ
--------------------
๋๊ฐ ์ด์์ ํ๋ก์ธ์๋ฅผ ๊ฐ์ง ์์คํ
์ด ์๋ค๋ฉด, ์์คํ
์ ๋๊ฐ ์ด์์ CPU ๋ ๋์์
๊ฐ์ ๋ฐ์ดํฐ์ ๋ํ ์์
์ ํ ์ ์์ต๋๋ค. ์ด๋ ๋๊ธฐํ ๋ฌธ์ ๋ฅผ ์ผ์ผํฌ ์ ์๊ณ ,
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ์ผ๋ฐ์ ๋ฐฉ๋ฒ์ ๋ฝ์ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค. ํ์ง๋ง, ๋ฝ์ ์๋นํ
๋น์ฉ์ด ๋น์ธ์ ๊ฐ๋ฅํ๋ฉด ๋ฝ์ ์ฌ์ฉํ์ง ์๊ณ ์ผ์ ์ฒ๋ฆฌํ๋ ๊ฒ์ด ๋ซ์ต๋๋ค. ์ด๋ฐ
๊ฒฝ์ฐ, ๋ CPU ๋ชจ๋์ ์ํฅ์ ๋ผ์น๋ ์คํผ๋ ์ด์
๋ค์ ์ค๋์์ ๋ง๊ธฐ ์ํด ์ ์คํ๊ฒ
์์๊ฐ ๋ง์ถฐ์ ธ์ผ ํฉ๋๋ค.
์๋ฅผ ๋ค์ด, R/W ์ธ๋งํฌ์ด์ ๋๋ฆฐ ์ํ๊ฒฝ๋ก (slow path) ๋ฅผ ์๊ฐํด ๋ด
์๋ค.
์ธ๋งํฌ์ด๋ฅผ ์ํด ๋๊ธฐ๋ฅผ ํ๋ ํ๋์ ํ๋ก์ธ์ค๊ฐ ์์ ์ ์คํ ์ค ์ผ๋ถ๋ฅผ ์ด
์ธ๋งํฌ์ด์ ๋๊ธฐ ํ๋ก์ธ์ค ๋ฆฌ์คํธ์ ๋งํฌํ ์ฑ๋ก ์์ต๋๋ค:
struct rw_semaphore {
...
spinlock_t lock;
struct list_head waiters;
};
struct rwsem_waiter {
struct list_head list;
struct task_struct *task;
};
ํน์ ๋๊ธฐ ์ํ ํ๋ก์ธ์ค๋ฅผ ๊นจ์ฐ๊ธฐ ์ํด, up_read() ๋ up_write() ํจ์๋ ๋ค์๊ณผ
๊ฐ์ ์ผ์ ํฉ๋๋ค:
(1) ๋ค์ ๋๊ธฐ ์ํ ํ๋ก์ธ์ค ๋ ์ฝ๋๋ ์ด๋์๋์ง ์๊ธฐ ์ํด ์ด ๋๊ธฐ ์ํ
ํ๋ก์ธ์ค ๋ ์ฝ๋์ next ํฌ์ธํฐ๋ฅผ ์ฝ์ต๋๋ค;
(2) ์ด ๋๊ธฐ ์ํ ํ๋ก์ธ์ค์ task ๊ตฌ์กฐ์ฒด๋ก์ ํฌ์ธํฐ๋ฅผ ์ฝ์ต๋๋ค;
(3) ์ด ๋๊ธฐ ์ํ ํ๋ก์ธ์ค๊ฐ ์ธ๋งํฌ์ด๋ฅผ ํ๋ํ์์ ์๋ฆฌ๊ธฐ ์ํด task
ํฌ์ธํฐ๋ฅผ ์ด๊ธฐํ ํฉ๋๋ค;
(4) ํด๋น ํ์คํฌ์ ๋ํด wake_up_process() ๋ฅผ ํธ์ถํฉ๋๋ค; ๊ทธ๋ฆฌ๊ณ
(5) ํด๋น ๋๊ธฐ ์ํ ํ๋ก์ธ์ค์ task ๊ตฌ์กฐ์ฒด๋ฅผ ์ก๊ณ ์๋ ๋ ํผ๋ฐ์ค๋ฅผ ํด์ ํฉ๋๋ค.
๋ฌ๋ฆฌ ๋งํ์๋ฉด, ๋ค์ ์ด๋ฒคํธ ์ํ์ค๋ฅผ ์ํํด์ผ ํฉ๋๋ค:
LOAD waiter->list.next;
LOAD waiter->task;
STORE waiter->task;
CALL wakeup
RELEASE task
๊ทธ๋ฆฌ๊ณ ์ด ์ด๋ฒคํธ๋ค์ด ๋ค๋ฅธ ์์๋ก ์ํ๋๋ค๋ฉด, ์ค๋์์ด ์ผ์ด๋ ์ ์์ต๋๋ค.
ํ๋ฒ ์ธ๋งํฌ์ด์ ๋๊ธฐ์ค์ ๋ค์ด๊ฐ๊ณ ์ธ๋งํฌ์ด ๋ฝ์ ๋์๋ค๋ฉด, ํด๋น ๋๊ธฐ ํ๋ก์ธ์ค๋
๋ฝ์ ๋ค์๋ ์ก์ง ์์ต๋๋ค; ๋์ ์์ ์ task ํฌ์ธํฐ๊ฐ ์ด๊ธฐํ ๋๊ธธ ๊ธฐ๋ค๋ฆฝ๋๋ค.
๊ทธ ๋ ์ฝ๋๋ ๋๊ธฐ ํ๋ก์ธ์ค์ ์คํ์ ์๊ธฐ ๋๋ฌธ์, ๋ฆฌ์คํธ์ next ํฌ์ธํฐ๊ฐ ์ฝํ์ง๊ธฐ
_์ ์_ task ํฌ์ธํฐ๊ฐ ์ง์์ง๋ค๋ฉด, ๋ค๋ฅธ CPU ๋ ํด๋น ๋๊ธฐ ํ๋ก์ธ์ค๋ฅผ ์์ํด ๋ฒ๋ฆฌ๊ณ
up*() ํจ์๊ฐ next ํฌ์ธํฐ๋ฅผ ์ฝ๊ธฐ ์ ์ ๋๊ธฐ ํ๋ก์ธ์ค์ ์คํ์ ๋ง๊ตฌ ๊ฑด๋๋ฆด ์
์์ต๋๋ค.
๊ทธ๋ ๊ฒ ๋๋ฉด ์์ ์ด๋ฒคํธ ์ํ์ค์ ์ด๋ค ์ผ์ด ์ผ์ด๋๋์ง ์๊ฐํด ๋ณด์ฃ :
CPU 1 CPU 2
=============================== ===============================
down_xxx()
Queue waiter
Sleep
up_yyy()
LOAD waiter->task;
STORE waiter->task;
Woken up by other event
<preempt>
Resume processing
down_xxx() returns
call foo()
foo() clobbers *waiter
</preempt>
LOAD waiter->list.next;
--- OOPS ---
์ด ๋ฌธ์ ๋ ์ธ๋งํฌ์ด ๋ฝ์ ์ฌ์ฉ์ผ๋ก ํด๊ฒฐ๋ ์๋ ์๊ฒ ์ง๋ง, ๊ทธ๋ ๊ฒ ๋๋ฉด ๊นจ์ด๋ ํ์
down_xxx() ํจ์๊ฐ ๋ถํ์ํ๊ฒ ์คํ๋ฝ์ ๋๋ค์ ์ป์ด์ผ๋ง ํฉ๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ๋ฒ์ฉ SMP ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ ์ถ๊ฐํ๋ ๊ฒ๋๋ค:
LOAD waiter->list.next;
LOAD waiter->task;
smp_mb();
STORE waiter->task;
CALL wakeup
RELEASE task
์ด ๊ฒฝ์ฐ์, ๋ฐฐ๋ฆฌ์ด๋ ์์คํ
์ ๋๋จธ์ง CPU ๋ค์๊ฒ ๋ชจ๋ ๋ฐฐ๋ฆฌ์ด ์์ ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค๊ฐ
๋ฐฐ๋ฆฌ์ด ๋ค์ ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค๋ณด๋ค ์์ ์ผ์ด๋ ๊ฒ์ผ๋ก ๋ณด์ด๊ฒ ๋ง๋ญ๋๋ค. ๋ฐฐ๋ฆฌ์ด ์์
๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค๋ค์ด ๋ฐฐ๋ฆฌ์ด ๋ช
๋ น ์์ฒด๊ฐ ์๋ฃ๋๋ ์์ ๊น์ง ์๋ฃ๋๋ค๊ณ ๋ ๋ณด์ฅํ์ง
_์์ต๋๋ค_.
(์ด๊ฒ ๋ฌธ์ ๊ฐ ๋์ง ์์) ๋จ์ผ ํ๋ก์ธ์ ์์คํ
์์ smp_mb() ๋ ์ค์ ๋ก๋ ๊ทธ์
์ปดํ์ผ๋ฌ๊ฐ CPU ์์์์ ์์๋ฅผ ๋ฐ๊พธ๊ฑฐ๋ ํ์ง ์๊ณ ์ฃผ์ด์ง ์์๋๋ก ๋ช
๋ น์
๋ด๋ฆฌ๋๋ก ํ๋ ์ปดํ์ผ๋ฌ ๋ฐฐ๋ฆฌ์ด์ผ ๋ฟ์
๋๋ค. ์ค์ง ํ๋์ CPU ๋ง ์์ผ๋, CPU ์
์์กด์ฑ ์์ ๋ก์ง์ด ๊ทธ ์ธ์ ๋ชจ๋ ๊ฒ์ ์์์ ์ฒ๋ฆฌํ ๊ฒ๋๋ค.
์ดํ ๋ฏน ์คํผ๋ ์ด์
-----------------
์ดํ ๋ฏน ์คํผ๋ ์ด์
์ ๊ธฐ์ ์ ์ผ๋ก ํ๋ก์ธ์๊ฐ ์ํธ์์ฉ์ผ๋ก ๋ถ๋ฅ๋๋ฉฐ ๊ทธ ์ค ์ผ๋ถ๋
์ ์ฒด ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ ๋ดํฌํ๊ณ ๋ ์ผ๋ถ๋ ๋ดํฌํ์ง ์์ง๋ง, ์ปค๋์์ ์๋นํ
์์กด์ ์ผ๋ก ์ฌ์ฉํ๋ ๊ธฐ๋ฅ ์ค ํ๋์
๋๋ค.
๋ฉ๋ชจ๋ฆฌ์ ์ด๋ค ์ํ๋ฅผ ์์ ํ๊ณ ํด๋น ์ํ์ ๋ํ (์์ ์ ๋๋ ์ต์ ์) ์ ๋ณด๋ฅผ
๋ฆฌํดํ๋ ์ดํ ๋ฏน ์คํผ๋ ์ด์
์ ๋ชจ๋ SMP-์กฐ๊ฑด์ ๋ฒ์ฉ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด(smp_mb())๋ฅผ
์ค์ ์คํผ๋ ์ด์
์ ์๊ณผ ๋ค์ ๋ดํฌํฉ๋๋ค. ์ด๋ฐ ์คํผ๋ ์ด์
์ ๋ค์์ ๊ฒ๋ค์
ํฌํจํฉ๋๋ค:
xchg();
atomic_xchg(); atomic_long_xchg();
atomic_inc_return(); atomic_long_inc_return();
atomic_dec_return(); atomic_long_dec_return();
atomic_add_return(); atomic_long_add_return();
atomic_sub_return(); atomic_long_sub_return();
atomic_inc_and_test(); atomic_long_inc_and_test();
atomic_dec_and_test(); atomic_long_dec_and_test();
atomic_sub_and_test(); atomic_long_sub_and_test();
atomic_add_negative(); atomic_long_add_negative();
test_and_set_bit();
test_and_clear_bit();
test_and_change_bit();
/* exchange ์กฐ๊ฑด์ด ์ฑ๊ณตํ ๋ */
cmpxchg();
atomic_cmpxchg(); atomic_long_cmpxchg();
atomic_add_unless(); atomic_long_add_unless();
์ด๊ฒ๋ค์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด ํจ๊ณผ๊ฐ ํ์ํ ACQUIRE ๋ถ๋ฅ์ RELEASE ๋ถ๋ฅ ์คํผ๋ ์ด์
๋ค์
๊ตฌํํ ๋, ๊ทธ๋ฆฌ๊ณ ๊ฐ์ฒด ํด์ ๋ฅผ ์ํด ๋ ํผ๋ฐ์ค ์นด์ดํฐ๋ฅผ ์กฐ์ ํ ๋, ์๋ฌต์ ๋ฉ๋ชจ๋ฆฌ
๋ฐฐ๋ฆฌ์ด ํจ๊ณผ๊ฐ ํ์ํ ๊ณณ ๋ฑ์ ์ฌ์ฉ๋ฉ๋๋ค.
๋ค์์ ์คํผ๋ ์ด์
๋ค์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ ๋ดํฌํ์ง _์๊ธฐ_ ๋๋ฌธ์ ๋ฌธ์ ๊ฐ ๋ ์
์์ง๋ง, RELEASE ๋ถ๋ฅ์ ์คํผ๋ ์ด์
๋ค๊ณผ ๊ฐ์ ๊ฒ๋ค์ ๊ตฌํํ ๋ ์ฌ์ฉ๋ ์๋
์์ต๋๋ค:
atomic_set();
set_bit();
clear_bit();
change_bit();
์ด๊ฒ๋ค์ ์ฌ์ฉํ ๋์๋ ํ์ํ๋ค๋ฉด ์ ์ ํ (์๋ฅผ ๋ค๋ฉด smp_mb__before_atomic()
๊ฐ์) ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๊ฐ ๋ช
์์ ์ผ๋ก ํจ๊ป ์ฌ์ฉ๋์ด์ผ ํฉ๋๋ค.
์๋์ ๊ฒ๋ค๋ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ ๋ดํฌํ์ง _์๊ธฐ_ ๋๋ฌธ์, ์ผ๋ถ ํ๊ฒฝ์์๋ (์๋ฅผ
๋ค๋ฉด smp_mb__before_atomic() ๊ณผ ๊ฐ์) ๋ช
์์ ์ธ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด ์ฌ์ฉ์ด ํ์ํฉ๋๋ค.
atomic_add();
atomic_sub();
atomic_inc();
atomic_dec();
์ด๊ฒ๋ค์ด ํต๊ณ ์์ฑ์ ์ํด ์ฌ์ฉ๋๋ค๋ฉด, ๊ทธ๋ฆฌ๊ณ ํต๊ณ ๋ฐ์ดํฐ ์ฌ์ด์ ๊ด๊ณ๊ฐ ์กด์ฌํ์ง
์๋๋ค๋ฉด ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ ํ์์น ์์ ๊ฒ๋๋ค.
๊ฐ์ฒด์ ์๋ช
์ ๊ด๋ฆฌํ๊ธฐ ์ํด ๋ ํผ๋ฐ์ค ์นด์ดํ
๋ชฉ์ ์ผ๋ก ์ฌ์ฉ๋๋ค๋ฉด, ๋ ํผ๋ฐ์ค
์นด์ดํฐ๋ ๋ฝ์ผ๋ก ๋ณดํธ๋๋ ์น์
์์๋ง ์กฐ์ ๋๊ฑฐ๋ ํธ์ถํ๋ ์ชฝ์ด ์ด๋ฏธ ์ถฉ๋ถํ
๋ ํผ๋ฐ์ค๋ฅผ ์ก๊ณ ์์ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ ์๋ง ํ์ ์์ ๊ฒ๋๋ค.
๋ง์ฝ ์ด๋ค ๋ฝ์ ๊ตฌ์ฑํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ค๋ฉด, ๋ฝ ๊ด๋ จ ๋์์ ์ผ๋ฐ์ ์ผ๋ก ์์
์ ํน์
์์๋๋ก ์งํํด์ผ ํ๋ฏ๋ก ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๊ฐ ํ์ํ ์ ์์ต๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก, ๊ฐ ์ฌ์ฉ์ฒ์์๋ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๊ฐ ํ์ํ์ง ์๋์ง ์ถฉ๋ถํ ๊ณ ๋ คํด์ผ
ํฉ๋๋ค.
์๋์ ์คํผ๋ ์ด์
๋ค์ ํน๋ณํ ๋ฝ ๊ด๋ จ ๋์๋ค์
๋๋ค:
test_and_set_bit_lock();
clear_bit_unlock();
__clear_bit_unlock();
์ด๊ฒ๋ค์ ACQUIRE ๋ฅ์ RELEASE ๋ฅ์ ์คํผ๋ ์ด์
๋ค์ ๊ตฌํํฉ๋๋ค. ๋ฝ ๊ด๋ จ ๋๊ตฌ๋ฅผ
๊ตฌํํ ๋์๋ ์ด๊ฒ๋ค์ ์ข ๋ ์ ํธํ๋ ํธ์ด ๋์๋ฐ, ์ด๊ฒ๋ค์ ๊ตฌํ์ ๋ง์
์ํคํ
์ณ์์ ์ต์ ํ ๋ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค.
[!] ์ด๋ฐ ์ํฉ์ ์ฌ์ฉํ ์ ์๋ ํน์ํ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด ๋๊ตฌ๋ค์ด ์์ต๋๋ค๋ง, ์ผ๋ถ
CPU ์์๋ ์ฌ์ฉ๋๋ ์ดํ ๋ฏน ์ธ์คํธ๋ญ์
์์ฒด์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๊ฐ ๋ดํฌ๋์ด ์์ด์
์ดํ ๋ฏน ์คํผ๋ ์ด์
๊ณผ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ ํจ๊ป ์ฌ์ฉํ๋ ๊ฒ ๋ถํ์ํ ์ผ์ด ๋ ์
์๋๋ฐ, ๊ทธ๋ฐ ๊ฒฝ์ฐ์ ์ด ํน์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด ๋๊ตฌ๋ค์ no-op ์ด ๋์ด ์ค์ง์ ์ผ๋ก
์๋ฌด์ผ๋ ํ์ง ์์ต๋๋ค.
๋ ๋ง์ ๋ด์ฉ์ ์ํด์ Documentation/atomic_ops.txt ๋ฅผ ์ฐธ๊ณ ํ์ธ์.
๋๋ฐ์ด์ค ์ก์ธ์ค
---------------
๋ง์ ๋๋ฐ์ด์ค๊ฐ ๋ฉ๋ชจ๋ฆฌ ๋งคํ ๊ธฐ๋ฒ์ผ๋ก ์ ์ด๋ ์ ์๋๋ฐ, ๊ทธ๋ ๊ฒ ์ ์ด๋๋
๋๋ฐ์ด์ค๋ CPU ์๋ ๋จ์ง ํน์ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ์งํฉ์ฒ๋ผ ๋ณด์ด๊ฒ ๋ฉ๋๋ค. ๋๋ผ์ด๋ฒ๋
๊ทธ๋ฐ ๋๋ฐ์ด์ค๋ฅผ ์ ์ดํ๊ธฐ ์ํด ์ ํํ ์ฌ๋ฐ๋ฅธ ์์๋ก ์ฌ๋ฐ๋ฅธ ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค๋ฅผ
๋ง๋ค์ด์ผ ํฉ๋๋ค.
ํ์ง๋ง, ์ก์ธ์ค๋ค์ ์ฌ๋ฐฐ์น ํ๊ฑฐ๋ ์กฐํฉํ๊ฑฐ๋ ๋ณํฉํ๋๊ฒ ๋ ํจ์จ์ ์ด๋ผ ํ๋จํ๋
์๋ฆฌํ CPU ๋ ์ปดํ์ผ๋ฌ๋ค์ ์ฌ์ฉํ๋ฉด ๋๋ผ์ด๋ฒ ์ฝ๋์ ์กฐ์ฌ์ค๋ฝ๊ฒ ์์ ๋ง์ถฐ์ง
์ก์ธ์ค๋ค์ด ๋๋ฐ์ด์ค์๋ ์์ฒญ๋ ์์๋๋ก ๋์ฐฉํ์ง ๋ชปํ๊ฒ ํ ์ ์๋ - ๋๋ฐ์ด์ค๊ฐ
์ค๋์์ ํ๊ฒ ํ - ์ ์ฌ์ ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์์ต๋๋ค.
๋ฆฌ๋
์ค ์ปค๋ ๋ด๋ถ์์, I/O ๋ ์ด๋ป๊ฒ ์ก์ธ์ค๋ค์ ์ ์ ํ ์์ฐจ์ ์ด๊ฒ ๋ง๋ค ์ ์๋์ง
์๊ณ ์๋, - inb() ๋ writel() ๊ณผ ๊ฐ์ - ์ ์ ํ ์ก์ธ์ค ๋ฃจํด์ ํตํด ์ด๋ฃจ์ด์ ธ์ผ๋ง
ํฉ๋๋ค. ์ด๊ฒ๋ค์ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ์๋ ๋ช
์์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด ์ ํจ๊ป ์ฌ์ฉ๋ ํ์๊ฐ
์์ต๋๋ค๋ง, ๋ค์์ ๋๊ฐ์ง ์ํฉ์์๋ ๋ช
์์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๊ฐ ํ์ํ ์ ์์ต๋๋ค:
(1) ์ผ๋ถ ์์คํ
์์ I/O ์คํ ์ด๋ ๋ชจ๋ CPU ์ ์ผ๊ด๋๊ฒ ์์ ๋ง์ถฐ์ง์ง ์๋๋ฐ,
๋ฐ๋ผ์ _๋ชจ๋ _ ์ผ๋ฐ์ ์ธ ๋๋ผ์ด๋ฒ๋ค์ ๋ฝ์ด ์ฌ์ฉ๋์ด์ผ๋ง ํ๊ณ ์ด ํฌ๋ฆฌํฐ์ปฌ
์น์
์ ๋น ์ ธ๋์ค๊ธฐ ์ ์ mmiowb() ๊ฐ ๊ผญ ํธ์ถ๋์ด์ผ ํฉ๋๋ค.
(2) ๋ง์ฝ ์ก์ธ์ค ํจ์๋ค์ด ์ํ๋ ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค ์์ฑ์ ๊ฐ๋ I/O ๋ฉ๋ชจ๋ฆฌ ์๋์ฐ๋ฅผ
์ฌ์ฉํ๋ค๋ฉด, ์์๋ฅผ ๊ฐ์ ํ๊ธฐ ์ํด์ _mandatory_ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๊ฐ ํ์ํฉ๋๋ค.
๋ ๋ง์ ์ ๋ณด๋ฅผ ์ํด์ Documentation/DocBook/deviceiobook.tmpl ์ ์ฐธ๊ณ ํ์ญ์์ค.
์ธํฐ๋ฝํธ
--------
๋๋ผ์ด๋ฒ๋ ์์ ์ ์ธํฐ๋ฝํธ ์๋น์ค ๋ฃจํด์ ์ํด ์ธํฐ๋ฝํธ ๋นํ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ผ์ด๋ฒ์ ์ด ๋ ๋ถ๋ถ์ ์๋ก์ ๋๋ฐ์ด์ค ์ ์ด ๋๋ ์ก์ธ์ค ๋ถ๋ถ๊ณผ ์ํธ ๊ฐ์ญํ ์
์์ต๋๋ค.
์ค์ค๋ก์๊ฒ ์ธํฐ๋ฝํธ ๋นํ๋ ๊ฑธ ๋ถ๊ฐ๋ฅํ๊ฒ ํ๊ณ , ๋๋ผ์ด๋ฒ์ ํฌ๋ฆฌํฐ์ปฌํ
์คํผ๋ ์ด์
๋ค์ ๋ชจ๋ ์ธํฐ๋ฝํธ๊ฐ ๋ถ๊ฐ๋ฅํ๊ฒ ๋ ์์ญ์ ์ง์ด๋ฃ๊ฑฐ๋ ํ๋ ๋ฐฉ๋ฒ (๋ฝ์
ํ ํํ) ์ผ๋ก ์ด๋ฐ ์ํธ ๊ฐ์ญ์ - ์ต์ํ ๋ถ๋ถ์ ์ผ๋ก๋ผ๋ - ์ค์ผ ์ ์์ต๋๋ค.
๋๋ผ์ด๋ฒ์ ์ธํฐ๋ฝํธ ๋ฃจํด์ด ์คํ ์ค์ธ ๋์, ํด๋น ๋๋ผ์ด๋ฒ์ ์ฝ์ด๋ ๊ฐ์ CPU ์์
์ํ๋์ง ์์ ๊ฒ์ด๋ฉฐ, ํ์ฌ์ ์ธํฐ๋ฝํธ๊ฐ ์ฒ๋ฆฌ๋๋ ์ค์๋ ๋๋ค์ ์ธํฐ๋ฝํธ๊ฐ
์ผ์ด๋์ง ๋ชปํ๋๋ก ๋์ด ์์ผ๋ ์ธํฐ๋ฝํธ ํธ๋ค๋ฌ๋ ๊ทธ์ ๋ํด์๋ ๋ฝ์ ์ก์ง ์์๋
๋ฉ๋๋ค.
ํ์ง๋ง, ์ด๋๋ ์ค ๋ ์ง์คํฐ์ ๋ฐ์ดํฐ ๋ ์ง์คํฐ๋ฅผ ๊ฐ๋ ์ด๋๋ท ์นด๋๋ฅผ ๋ค๋ฃจ๋
๋๋ผ์ด๋ฒ๋ฅผ ์๊ฐํด ๋ด
์๋ค. ๋ง์ฝ ์ด ๋๋ผ์ด๋ฒ์ ์ฝ์ด๊ฐ ์ธํฐ๋ฝํธ๋ฅผ ๋นํ์ฑํ์ํจ
์ฑ๋ก ์ด๋๋ท ์นด๋์ ๋ํํ๊ณ ๋๋ผ์ด๋ฒ์ ์ธํฐ๋ฝํธ ํธ๋ค๋ฌ๊ฐ ํธ์ถ๋์๋ค๋ฉด:
LOCAL IRQ DISABLE
writew(ADDR, 3);
writew(DATA, y);
LOCAL IRQ ENABLE
<interrupt>
writew(ADDR, 4);
q = readw(DATA);
</interrupt>
๋ง์ฝ ์์ ๊ท์น์ด ์ถฉ๋ถํ ์ํ๋์ด ์๋ค๋ฉด ๋ฐ์ดํฐ ๋ ์ง์คํฐ์์ ์คํ ์ด๋ ์ด๋๋ ์ค
๋ ์ง์คํฐ์ ๋๋ฒ์งธ๋ก ํํด์ง๋ ์คํ ์ด ๋ค์ ์ผ์ด๋ ์๋ ์์ต๋๋ค:
STORE *ADDR = 3, STORE *ADDR = 4, STORE *DATA = y, q = LOAD *DATA
๋ง์ฝ ์์ ๊ท์น์ด ์ถฉ๋ถํ ์ํ๋์ด ์๊ณ ๋ฌต์์ ์ผ๋ก๋ ๋ช
์์ ์ผ๋ก๋ ๋ฐฐ๋ฆฌ์ด๊ฐ
์ฌ์ฉ๋์ง ์์๋ค๋ฉด ์ธํฐ๋ฝํธ ๋นํ์ฑํ ์น์
์์ ์ผ์ด๋ ์ก์ธ์ค๊ฐ ๋ฐ๊นฅ์ผ๋ก ์์ด์
์ธํฐ๋ฝํธ ๋ด์์ ์ผ์ด๋ ์ก์ธ์ค์ ์์ผ ์ ์๋ค๊ณ - ๊ทธ๋ฆฌ๊ณ ๊ทธ ๋ฐ๋๋ - ๊ฐ์ ํด์ผ๋ง
ํฉ๋๋ค.
๊ทธ๋ฐ ์์ญ ์์์ ์ผ์ด๋๋ I/O ์ก์ธ์ค๋ค์ ์๊ฒฉํ ์์ ๊ท์น์ I/O ๋ ์ง์คํฐ์
๋ฌต์์ I/O ๋ฐฐ๋ฆฌ์ด๋ฅผ ํ์ฑํ๋ ๋๊ธฐ์ (synchronous) ๋ก๋ ์คํผ๋ ์ด์
์ ํฌํจํ๊ธฐ
๋๋ฌธ์ ์ผ๋ฐ์ ์ผ๋ก๋ ์ด๋ฐ๊ฒ ๋ฌธ์ ๊ฐ ๋์ง ์์ต๋๋ค. ๋ง์ฝ ์ด๊ฑธ๋ก๋ ์ถฉ๋ถ์น ์๋ค๋ฉด
mmiowb() ๊ฐ ๋ช
์์ ์ผ๋ก ์ฌ์ฉ๋ ํ์๊ฐ ์์ต๋๋ค.
ํ๋์ ์ธํฐ๋ฝํธ ๋ฃจํด๊ณผ ๋ณ๋์ CPU ์์ ์ํ์ค์ด๋ฉฐ ์๋ก ํต์ ์ ํ๋ ๋ ๋ฃจํด
์ฌ์ด์๋ ๋น์ทํ ์ํฉ์ด ์ผ์ด๋ ์ ์์ต๋๋ค. ๋ง์ฝ ๊ทธ๋ฐ ๊ฒฝ์ฐ๊ฐ ๋ฐ์ํ ๊ฐ๋ฅ์ฑ์ด
์๋ค๋ฉด, ์์๋ฅผ ๋ณด์ฅํ๊ธฐ ์ํด ์ธํฐ๋ฝํธ ๋นํ์ฑํ ๋ฝ์ด ์ฌ์ฉ๋์ด์ ธ์ผ๋ง ํฉ๋๋ค.
======================
์ปค๋ I/O ๋ฐฐ๋ฆฌ์ด์ ํจ๊ณผ
======================
I/O ๋ฉ๋ชจ๋ฆฌ์ ์ก์ธ์คํ ๋, ๋๋ผ์ด๋ฒ๋ ์ ์ ํ ์ก์ธ์ค ํจ์๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค:
(*) inX(), outX():
์ด๊ฒ๋ค์ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ๋ณด๋ค๋ I/O ๊ณต๊ฐ์ ์ด์ผ๊ธฐ๋ฅผ ํ๋ ค๋ ์๋๋ก
๋ง๋ค์ด์ก์ต๋๋ค๋ง, ๊ทธ๊ฑด ๊ธฐ๋ณธ์ ์ผ๋ก CPU ๋ง๋ค ๋ค๋ฅธ ์ปจ์
์
๋๋ค. i386 ๊ณผ
x86_64 ํ๋ก์ธ์๋ค์ ํน๋ณํ I/O ๊ณต๊ฐ ์ก์ธ์ค ์ฌ์ดํด๊ณผ ๋ช
๋ น์ด๋ฅผ ์ค์ ๋ก ๊ฐ์ง๊ณ
์์ง๋ง, ๋ค๋ฅธ ๋ง์ CPU ๋ค์๋ ๊ทธ๋ฐ ์ปจ์
์ด ์กด์ฌํ์ง ์์ต๋๋ค.
๋ค๋ฅธ ๊ฒ๋ค ์ค์์๋ PCI ๋ฒ์ค๊ฐ I/O ๊ณต๊ฐ ์ปจ์
์ ์ ์ํ๋๋ฐ, ์ด๋ - i386 ๊ณผ
x86_64 ๊ฐ์ CPU ์์ - CPU ์ I/O ๊ณต๊ฐ ์ปจ์
์ผ๋ก ์ฝ๊ฒ ๋งค์น๋ฉ๋๋ค. ํ์ง๋ง,
๋์ฒดํ I/O ๊ณต๊ฐ์ด ์๋ CPU ์์๋ CPU ์ ๋ฉ๋ชจ๋ฆฌ ๋งต์ ๊ฐ์ I/O ๊ณต๊ฐ์ผ๋ก
๋งคํ๋ ์๋ ์์ต๋๋ค.
์ด ๊ณต๊ฐ์ผ๋ก์ ์ก์ธ์ค๋ (i386 ๋ฑ์์๋) ์์ ํ๊ฒ ๋๊ธฐํ ๋ฉ๋๋ค๋ง, ์ค๊ฐ์
(PCI ํธ์คํธ ๋ธ๋ฆฌ์ง์ ๊ฐ์) ๋ธ๋ฆฌ์ง๋ค์ ์ด๋ฅผ ์์ ํ ๋ณด์ฅํ์ง ์์์๋
์์ต๋๋ค.
์ด๊ฒ๋ค์ ์ํธ๊ฐ์ ์์๋ ์์ ํ๊ฒ ๋ณด์ฅ๋ฉ๋๋ค.
๋ค๋ฅธ ํ์
์ ๋ฉ๋ชจ๋ฆฌ ์คํผ๋ ์ด์
, I/O ์คํผ๋ ์ด์
์ ๋ํ ์์๋ ์์ ํ๊ฒ
๋ณด์ฅ๋์ง๋ ์์ต๋๋ค.
(*) readX(), writeX():
์ด๊ฒ๋ค์ด ์ํ ์์ฒญ๋๋ CPU ์์ ์๋ก์๊ฒ ์์ ํ ์์๊ฐ ๋ง์ถฐ์ง๊ณ ๋
๋ฆฝ์ ์ผ๋ก
์ํ๋๋์ง์ ๋ํ ๋ณด์ฅ ์ฌ๋ถ๋ ์ด๋ค์ด ์ก์ธ์ค ํ๋ ๋ฉ๋ชจ๋ฆฌ ์๋์ฐ์ ์ ์๋
ํน์ฑ์ ์ํด ๊ฒฐ์ ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์ต์ ์ i386 ์ํคํ
์ณ ๋จธ์ ์์๋ MTRR
๋ ์ง์คํฐ๋ก ์ด ํน์ฑ์ด ์กฐ์ ๋ฉ๋๋ค.
์ผ๋ฐ์ ์ผ๋ก๋, ํ๋ฆฌํ์น (prefetch) ๊ฐ๋ฅํ ๋๋ฐ์ด์ค๋ฅผ ์ก์ธ์ค ํ๋๊ฒ
์๋๋ผ๋ฉด, ์ด๊ฒ๋ค์ ์์ ํ ์์๊ฐ ๋ง์ถฐ์ง๊ณ ๊ฒฐํฉ๋์ง ์๊ฒ ๋ณด์ฅ๋ ๊ฒ๋๋ค.
ํ์ง๋ง, (PCI ๋ธ๋ฆฌ์ง์ ๊ฐ์) ์ค๊ฐ์ ํ๋์จ์ด๋ ์์ ์ด ์ํ๋ค๋ฉด ์งํ์
์ฐ๊ธฐ์ํฌ ์ ์์ต๋๋ค; ์คํ ์ด ๋ช
๋ น์ ์ค์ ๋ก ํ๋์จ์ด๋ก ๋ด๋ ค๋ณด๋ด๊ธฐ(flush)
์ํด์๋ ๊ฐ์ ์์น๋ก๋ถํฐ ๋ก๋๋ฅผ ํ๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค๋ง[*], PCI ์ ๊ฒฝ์ฐ๋
๊ฐ์ ๋๋ฐ์ด์ค๋ ํ๊ฒฝ ๊ตฌ์ฑ ์์ญ์์์ ๋ก๋๋ง์ผ๋ก๋ ์ถฉ๋ถํ ๊ฒ๋๋ค.
[*] ์ฃผ์! ์ฐ์ฌ์ง ๊ฒ๊ณผ ๊ฐ์ ์์น๋ก๋ถํฐ์ ๋ก๋๋ฅผ ์๋ํ๋ ๊ฒ์ ์ค๋์์
์ผ์ผํฌ ์๋ ์์ต๋๋ค - ์๋ก 16650 Rx/Tx ์๋ฆฌ์ผ ๋ ์ง์คํฐ๋ฅผ ์๊ฐํด
๋ณด์ธ์.
ํ๋ฆฌํ์น ๊ฐ๋ฅํ I/O ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ฌ์ฉ๋๋ฉด, ์คํ ์ด ๋ช
๋ น๋ค์ด ์์๋ฅผ ์งํค๋๋ก
ํ๊ธฐ ์ํด mmiowb() ๋ฐฐ๋ฆฌ์ด๊ฐ ํ์ํ ์ ์์ต๋๋ค.
PCI ํธ๋์ญ์
์ฌ์ด์ ์ํธ์์ฉ์ ๋ํด ๋ ๋ง์ ์ ๋ณด๋ฅผ ์ํด์ PCI ๋ช
์ธ์๋ฅผ
์ฐธ๊ณ ํ์๊ธฐ ๋ฐ๋๋๋ค.
(*) readX_relaxed(), writeX_relaxed()
์ด๊ฒ๋ค์ readX() ์ writeX() ๋ ๋น์ทํ์ง๋ง, ๋ ์ํ๋ ๋ฉ๋ชจ๋ฆฌ ์์ ๋ณด์ฅ์
์ ๊ณตํฉ๋๋ค. ๊ตฌ์ฒด์ ์ผ๋ก, ์ด๊ฒ๋ค์ ์ผ๋ฐ์ ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค (์: DMA ๋ฒํผ) ์๋
LOCK ์ด๋ UNLOCK ์คํผ๋ ์ด์
๋ค์๋ ์์๋ฅผ ๋ณด์ฅํ์ง ์์ต๋๋ค. LOCK ์ด๋
UNLOCK ์คํผ๋ ์ด์
๋ค์ ๋ง์ถฐ์ง๋ ์์๊ฐ ํ์ํ๋ค๋ฉด, mmiowb() ๋ฐฐ๋ฆฌ์ด๊ฐ ์ฌ์ฉ๋
์ ์์ต๋๋ค. ๊ฐ์ ์ฃผ๋ณ ์ฅ์น์์ ์ํ๋ ์ก์ธ์ค๋ผ๋ฆฌ๋ ์์๊ฐ ์ง์ผ์ง์ ์์
๋์๊ธฐ ๋ฐ๋๋๋ค.
(*) ioreadX(), iowriteX()
์ด๊ฒ๋ค์ inX()/outX() ๋ readX()/writeX() ์ฒ๋ผ ์ค์ ๋ก ์ํํ๋ ์ก์ธ์ค์
์ข
๋ฅ์ ๋ฐ๋ผ ์ ์ ํ๊ฒ ์ํ๋ ๊ฒ์
๋๋ค.
===================================
๊ฐ์ ๋๋ ๊ฐ์ฅ ์ํ๋ ์คํ ์์ ๋ชจ๋ธ
===================================
์ปจ์
์ ์ผ๋ก CPU ๋ ์ฃผ์ด์ง ํ๋ก๊ทธ๋จ์ ๋ํด ํ๋ก๊ทธ๋จ ๊ทธ ์์ฒด์๋ ์ธ๊ณผ์ฑ (program
causality) ์ ์งํค๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๊ฒ ํ์ง๋ง ์ผ๋ฐ์ ์ผ๋ก๋ ์์๋ฅผ ๊ฑฐ์ ์ง์ผ์ฃผ์ง
์๋๋ค๊ณ ๊ฐ์ ๋์ด์ผ๋ง ํฉ๋๋ค. (i386 ์ด๋ x86_64 ๊ฐ์) ์ผ๋ถ CPU ๋ค์ ์ฝ๋
์ฌ๋ฐฐ์น์ (powerpc ๋ frv ์ ๊ฐ์) ๋ค๋ฅธ ๊ฒ๋ค์ ๋นํด ๊ฐํ ์ ์ฝ์ ๊ฐ์ง๋ง, ์ํคํ
์ณ
์ข
์์ ์ฝ๋ ์ด์ธ์ ์ฝ๋์์๋ ์์์ ๋ํ ์ ์ฝ์ด ๊ฐ์ฅ ์ํ๋ ๊ฒฝ์ฐ (DEC Alpha)
๋ฅผ ๊ฐ์ ํด์ผ ํฉ๋๋ค.
์ด ๋ง์, CPU ์๊ฒ ์ฃผ์ด์ง๋ ์ธ์คํธ๋ญ์
์คํธ๋ฆผ ๋ด์ ํ ์ธ์คํธ๋ญ์
์ด ์์
์ธ์คํธ๋ญ์
์ ์ข
์์ ์ด๋ผ๋ฉด ์์ ์ธ์คํธ๋ญ์
์ ๋ค์ ์ข
์์ ์ธ์คํธ๋ญ์
์ด ์คํ๋๊ธฐ
์ ์ ์๋ฃ[*]๋ ์ ์์ด์ผ ํ๋ค๋ ์ ์ฝ (๋ฌ๋ฆฌ ๋งํด์, ์ธ๊ณผ์ฑ์ด ์ง์ผ์ง๋ ๊ฒ์ผ๋ก
๋ณด์ด๊ฒ ํจ) ์ธ์๋ ์์ ์ด ์ํ๋ ์์๋๋ก - ์ฌ์ง์ด ๋ณ๋ ฌ์ ์ผ๋ก๋ - ๊ทธ ์คํธ๋ฆผ์
์คํํ ์ ์์์ ์๋ฏธํฉ๋๋ค
[*] ์ผ๋ถ ์ธ์คํธ๋ญ์
์ ํ๋ ์ด์์ ์ํฅ - ์กฐ๊ฑด ์ฝ๋๋ฅผ ๋ฐ๊พผ๋ค๋์ง, ๋ ์ง์คํฐ๋
๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ฐ๊พผ๋ค๋์ง - ์ ๋ง๋ค์ด๋ด๋ฉฐ, ๋ค๋ฅธ ์ธ์คํธ๋ญ์
์ ๋ค๋ฅธ ํจ๊ณผ์
์ข
์์ ์ผ ์ ์์ต๋๋ค.
CPU ๋ ์ต์ข
์ ์ผ๋ก ์๋ฌด ํจ๊ณผ๋ ๋ง๋ค์ง ์๋ ์ธ์คํธ๋ญ์
์ํ์ค๋ ์์ ๋ฒ๋ฆด ์๋
์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๋ง์ฝ ๋๊ฐ์ ์ฐ์๋๋ ์ธ์คํธ๋ญ์
์ด ๋ ๋ค ๊ฐ์ ๋ ์ง์คํฐ์
์ง์ ์ ์ธ ๊ฐ (immediate value) ์ ์ง์ด๋ฃ๋๋ค๋ฉด, ์ฒซ๋ฒ์งธ ์ธ์คํธ๋ญ์
์ ๋ฒ๋ ค์ง ์๋
์์ต๋๋ค.
๋น์ทํ๊ฒ, ์ปดํ์ผ๋ฌ ์ญ์ ํ๋ก๊ทธ๋จ์ ์ธ๊ณผ์ฑ๋ง ์ง์ผ์ค๋ค๋ฉด ์ธ์คํธ๋ญ์
์คํธ๋ฆผ์
์์ ์ด ๋ณด๊ธฐ์ ์ฌ๋ฐ๋ฅด๋ค ์๊ฐ๋๋๋๋ก ์ฌ๋ฐฐ์น ํ ์ ์์ต๋๋ค.
===============
CPU ์บ์์ ์ํฅ
===============
์บ์๋ ๋ฉ๋ชจ๋ฆฌ ์คํผ๋ ์ด์
๋ค์ด ์์คํ
์ ์ฒด์ ์ด๋ป๊ฒ ์ธ์ง๋๋์ง๋ CPU ์ ๋ฉ๋ชจ๋ฆฌ
์ฌ์ด์ ์กด์ฌํ๋ ์บ์๋ค, ๊ทธ๋ฆฌ๊ณ ์์คํ
์ํ์ ์ผ๊ด์ฑ์ ๊ด๋ฆฌํ๋ ๋ฉ๋ชจ๋ฆฌ ์ผ๊ด์ฑ
์์คํ
์ ์๋น ๋ถ๋ถ ์ํฅ์ ๋ฐ์ต๋๋ค.
ํ CPU ๊ฐ ์์คํ
์ ๋ค๋ฅธ ๋ถ๋ถ๋ค๊ณผ ์บ์๋ฅผ ํตํด ์ํธ์์ฉํ๋ค๋ฉด, ๋ฉ๋ชจ๋ฆฌ ์์คํ
์
CPU ์ ์บ์๋ค์ ํฌํจํด์ผ ํ๋ฉฐ, CPU ์ CPU ์์ ์ ์บ์ ์ฌ์ด์์์ ๋์์ ์ํ
๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ ๊ฐ์ ธ์ผ ํฉ๋๋ค. (๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ ๋
ผ๋ฆฌ์ ์ผ๋ก๋ ๋ค์ ๊ทธ๋ฆผ์
์ ์ ์์ ๋์ํฉ๋๋ค):
<--- CPU ---> : <----------- Memory ----------->
:
+--------+ +--------+ : +--------+ +-----------+
| | | | : | | | | +--------+
| CPU | | Memory | : | CPU | | | | |
| Core |--->| Access |----->| Cache |<-->| | | |
| | | Queue | : | | | |--->| Memory |
| | | | : | | | | | |
+--------+ +--------+ : +--------+ | | | |
: | Cache | +--------+
: | Coherency |
: | Mechanism | +--------+
+--------+ +--------+ : +--------+ | | | |
| | | | : | | | | | |
| CPU | | Memory | : | CPU | | |--->| Device |
| Core |--->| Access |----->| Cache |<-->| | | |
| | | Queue | : | | | | | |
| | | | : | | | | +--------+
+--------+ +--------+ : +--------+ +-----------+
:
:
ํน์ ๋ก๋๋ ์คํ ์ด๋ ํด๋น ์คํผ๋ ์ด์
์ ์์ฒญํ CPU ์ ์บ์ ๋ด์์ ๋์์ ์๋ฃํ
์๋ ์๊ธฐ ๋๋ฌธ์ ํด๋น CPU ์ ๋ฐ๊นฅ์๋ ๋ณด์ด์ง ์์ ์ ์์ง๋ง, ๋ค๋ฅธ CPU ๊ฐ ๊ด์ฌ์
๊ฐ๋๋ค๋ฉด ์บ์ ์ผ๊ด์ฑ ๋ฉ์ปค๋์ฆ์ด ํด๋น ์บ์๋ผ์ธ์ ํด๋น CPU ์๊ฒ ์ ๋ฌํ๊ณ , ํด๋น
๋ฉ๋ชจ๋ฆฌ ์์ญ์ ๋ํ ์คํผ๋ ์ด์
์ด ๋ฐ์ํ ๋๋ง๋ค ๊ทธ ์ํฅ์ ์ ํ์ํค๊ธฐ ๋๋ฌธ์, ํด๋น
์คํผ๋ ์ด์
์ ๋ฉ๋ชจ๋ฆฌ์ ์ค์ ๋ก ์ก์ธ์ค๋ฅผ ํ๊ฒ์ฒ๋ผ ๋ํ๋ ๊ฒ์
๋๋ค.
CPU ์ฝ์ด๋ ํ๋ก๊ทธ๋จ์ ์ธ๊ณผ์ฑ์ด ์ ์ง๋๋ค๊ณ ๋ง ์ฌ๊ฒจ์ง๋ค๋ฉด ์ธ์คํธ๋ญ์
๋ค์ ์ด๋ค
์์๋ก๋ ์ฌ๋ฐฐ์นํด์ ์ํํ ์ ์์ต๋๋ค. ์ผ๋ถ ์ธ์คํธ๋ญ์
๋ค์ ๋ก๋๋ ์คํ ์ด
์คํผ๋ ์ด์
์ ๋ง๋๋๋ฐ ์ด ์คํผ๋ ์ด์
๋ค์ ์ดํ ์ํ๋ ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค ํ์ ๋ค์ด๊ฐ๊ฒ
๋ฉ๋๋ค. ์ฝ์ด๋ ์ด ์คํผ๋ ์ด์
๋ค์ ํด๋น ํ์ ์ด๋ค ์์๋ก๋ ์ํ๋๋๋ก ๋ฃ์ ์
์๊ณ , ๋ค๋ฅธ ์ธ์คํธ๋ญ์
์ ์๋ฃ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋๋ก ๊ฐ์ ๋๊ธฐ ์ ๊น์ง๋ ์ํ์ ๊ณ์ํฉ๋๋ค.
๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๊ฐ ํ๋ ์ผ์ CPU ์ชฝ์์ ๋ฉ๋ชจ๋ฆฌ ์ชฝ์ผ๋ก ๋์ด๊ฐ๋ ์ก์ธ์ค๋ค์ ์์,
๊ทธ๋ฆฌ๊ณ ๊ทธ ์ก์ธ์ค์ ๊ฒฐ๊ณผ๊ฐ ์์คํ
์ ๋ค๋ฅธ ๊ด์ฐฐ์๋ค์๊ฒ ์ธ์ง๋๋ ์์๋ฅผ ์ ์ดํ๋
๊ฒ์
๋๋ค.
[!] CPU ๋ค์ ํญ์ ๊ทธ๋ค ์์ ์ ๋ก๋์ ์คํ ์ด๋ ํ๋ก๊ทธ๋จ ์์๋๋ก ์ผ์ด๋ ๊ฒ์ผ๋ก
๋ณด๊ธฐ ๋๋ฌธ์, ์ฃผ์ด์ง CPU ๋ด์์๋ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ฅผ ์ฌ์ฉํ ํ์๊ฐ _์์ต๋๋ค_.
[!] MMIO ๋ ๋ค๋ฅธ ๋๋ฐ์ด์ค ์ก์ธ์ค๋ค์ ์บ์ ์์คํ
์ ์ฐํํ ์๋ ์์ต๋๋ค. ์ฐํ
์ฌ๋ถ๋ ๋๋ฐ์ด์ค๊ฐ ์ก์ธ์ค ๋๋ ๋ฉ๋ชจ๋ฆฌ ์๋์ฐ์ ํน์ฑ์ ์ํด ๊ฒฐ์ ๋ ์๋ ์๊ณ , CPU
๊ฐ ๊ฐ์ง๊ณ ์์ ์ ์๋ ํน์ํ ๋๋ฐ์ด์ค ํต์ ์ธ์คํธ๋ญ์
์ ์ฌ์ฉ์ ์ํด์ ๊ฒฐ์ ๋
์๋ ์์ต๋๋ค.
์บ์ ์ผ๊ด์ฑ
-----------
ํ์ง๋ง ์ถ์ ์์์ ์ด์ผ๊ธฐํ ๊ฒ์ฒ๋ผ ๋จ์ํ์ง ์์ต๋๋ค: ์บ์๋ค์ ์ผ๊ด์ ์ผ ๊ฒ์ผ๋ก
๊ธฐ๋๋์ง๋ง, ๊ทธ ์ผ๊ด์ฑ์ด ์์์๋ ์ ์ฉ๋ ๊ฑฐ๋ผ๋ ๋ณด์ฅ์ ์์ต๋๋ค. ํ CPU ์์
๋ง๋ค์ด์ง ๋ณ๊ฒฝ ์ฌํญ์ ์ต์ข
์ ์ผ๋ก๋ ์์คํ
์ ๋ชจ๋ CPU ์๊ฒ ๋ณด์ฌ์ง๊ฒ ๋์ง๋ง, ๋ค๋ฅธ
CPU ๋ค์๊ฒ๋ ๊ฐ์ ์์๋ก ๋ณด์ด๊ฒ ๋ ๊ฑฐ๋ผ๋ ๋ณด์ฅ์ ์๋ค๋ ๋ป์
๋๋ค.
๋๊ฐ์ CPU (1 & 2) ๊ฐ ๋ฌ๋ ค ์๊ณ , ๊ฐ CPU ์ ๋๊ฐ์ ๋ฐ์ดํฐ ์บ์(CPU 1 ์ A/B ๋ฅผ,
CPU 2 ๋ C/D ๋ฅผ ๊ฐ์ต๋๋ค)๊ฐ ๋ณ๋ ฌ๋ก ์ฐ๊ฒฐ๋์ด ์๋ ์์คํ
์ ๋ค๋ฃฌ๋ค๊ณ ์๊ฐํด
๋ด
์๋ค:
:
: +--------+
: +---------+ | |
+--------+ : +--->| Cache A |<------->| |
| | : | +---------+ | |
| CPU 1 |<---+ | |
| | : | +---------+ | |
+--------+ : +--->| Cache B |<------->| |
: +---------+ | |
: | Memory |
: +---------+ | System |
+--------+ : +--->| Cache C |<------->| |
| | : | +---------+ | |
| CPU 2 |<---+ | |
| | : | +---------+ | |
+--------+ : +--->| Cache D |<------->| |
: +---------+ | |
: +--------+
:
์ด ์์คํ
์ด ๋ค์๊ณผ ๊ฐ์ ํน์ฑ์ ๊ฐ๋๋ค ์๊ฐํด ๋ด
์๋ค:
(*) ํ์๋ฒ ์บ์๋ผ์ธ์ ์บ์ A, ์บ์ C ๋๋ ๋ฉ๋ชจ๋ฆฌ์ ์์นํ ์ ์์;
(*) ์ง์๋ฒ ์บ์๋ผ์ธ์ ์บ์ B, ์บ์ D ๋๋ ๋ฉ๋ชจ๋ฆฌ์ ์์นํ ์ ์์;
(*) CPU ์ฝ์ด๊ฐ ํ๊ฐ์ ์บ์์ ์ ๊ทผํ๋ ๋์, ๋ค๋ฅธ ์บ์๋ - ๋ํฐ ์บ์๋ผ์ธ์
๋ฉ๋ชจ๋ฆฌ์ ๋ด๋ฆฌ๊ฑฐ๋ ์ถ์ธก์ฑ ๋ก๋๋ฅผ ํ๊ฑฐ๋ ํ๊ธฐ ์ํด - ์์คํ
์ ๋ค๋ฅธ ๋ถ๋ถ์
์ก์ธ์ค ํ๊ธฐ ์ํด ๋ฒ์ค๋ฅผ ์ฌ์ฉํ ์ ์์;
(*) ๊ฐ ์บ์๋ ์์คํ
์ ๋๋จธ์ง ๋ถ๋ถ๋ค๊ณผ ์ผ๊ด์ฑ์ ๋ง์ถ๊ธฐ ์ํด ํด๋น ์บ์์
์ ์ฉ๋์ด์ผ ํ ์คํผ๋ ์ด์
๋ค์ ํ๋ฅผ ๊ฐ์ง;
(*) ์ด ์ผ๊ด์ฑ ํ๋ ์บ์์ ์ด๋ฏธ ์กด์ฌํ๋ ๋ผ์ธ์ ๊ฐํด์ง๋ ํ๋ฒํ ๋ก๋์ ์ํด์๋
๋น์์ง์ง ์๋๋ฐ, ํ์ ์คํผ๋ ์ด์
๋ค์ด ์ด ๋ก๋์ ๊ฒฐ๊ณผ์ ์ํฅ์ ๋ผ์น ์ ์๋ค
ํ ์ง๋ผ๋ ๊ทธ๋ฌํจ.
์ด์ , ์ฒซ๋ฒ์งธ CPU ์์ ๋๊ฐ์ ์ฐ๊ธฐ ์คํผ๋ ์ด์
์ ๋ง๋๋๋ฐ, ํด๋น CPU ์ ์บ์์
์์ฒญ๋ ์์๋ก ์คํผ๋ ์ด์
์ด ๋๋ฌ๋จ์ ๋ณด์ฅํ๊ธฐ ์ํด ๋ ์คํผ๋ ์ด์
์ฌ์ด์ ์ฐ๊ธฐ
๋ฐฐ๋ฆฌ์ด๋ฅผ ์ฌ์ฉํ๋ ์ํฉ์ ์์ํด ๋ด
์๋ค:
CPU 1 CPU 2 COMMENT
=============== =============== =======================================
u == 0, v == 1 and p == &u, q == &u
v = 2;
smp_wmb(); v ์ ๋ณ๊ฒฝ์ด p ์ ๋ณ๊ฒฝ ์ ์ ๋ณด์ผ ๊ฒ์
๋ถ๋ช
ํ ํจ
<A:modify v=2> v ๋ ์ด์ ์บ์ A ์ ๋
์ ์ ์ผ๋ก ์กด์ฌํจ
p = &v;
<B:modify p=&v> p ๋ ์ด์ ์บ์ B ์ ๋
์ ์ ์ผ๋ก ์กด์ฌํจ
์ฌ๊ธฐ์์ ์ฐ๊ธฐ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ CPU 1 ์ ์บ์๊ฐ ์ฌ๋ฐ๋ฅธ ์์๋ก ์
๋ฐ์ดํธ ๋ ๊ฒ์ผ๋ก
์์คํ
์ ๋ค๋ฅธ CPU ๋ค์ด ์ธ์งํ๊ฒ ๋ง๋ญ๋๋ค. ํ์ง๋ง, ์ด์ ๋๋ฒ์งธ CPU ๊ฐ ๊ทธ ๊ฐ๋ค์
์ฝ์ผ๋ ค ํ๋ ์ํฉ์ ์๊ฐํด ๋ด
์๋ค:
CPU 1 CPU 2 COMMENT
=============== =============== =======================================
...
q = p;
x = *q;
์์ ๋๊ฐ์ ์ฝ๊ธฐ ์คํผ๋ ์ด์
์ ์์๋ ์์๋ก ์ผ์ด๋์ง ๋ชปํ ์ ์๋๋ฐ, ๋๋ฒ์งธ CPU
์ ํ ์บ์์ ๋ค๋ฅธ ์บ์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํด v ๋ฅผ ๋ด๊ณ ์๋ ์บ์๋ผ์ธ์ ํด๋น ์บ์์์
์
๋ฐ์ดํธ๊ฐ ์ง์ฐ๋๋ ์ฌ์ด, p ๋ฅผ ๋ด๊ณ ์๋ ์บ์๋ผ์ธ์ ๋๋ฒ์งธ CPU ์ ๋ค๋ฅธ ์บ์์
์
๋ฐ์ดํธ ๋์ด๋ฒ๋ ธ์ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค.
CPU 1 CPU 2 COMMENT
=============== =============== =======================================
u == 0, v == 1 and p == &u, q == &u
v = 2;
smp_wmb();
<A:modify v=2> <C:busy>
<C:queue v=2>
p = &v; q = p;
<D:request p>
<B:modify p=&v> <D:commit p=&v>
<D:read p>
x = *q;
<C:read *q> ์บ์์ ์
๋ฐ์ดํธ ๋๊ธฐ ์ ์ v ๋ฅผ ์ฝ์
<C:unbusy>
<C:commit v=2>
๊ธฐ๋ณธ์ ์ผ๋ก, ๋๊ฐ์ ์บ์๋ผ์ธ ๋ชจ๋ CPU 2 ์ ์ต์ข
์ ์ผ๋ก๋ ์
๋ฐ์ดํธ ๋ ๊ฒ์ด์ง๋ง,
๋ณ๋์ ๊ฐ์
์์ด๋, ์
๋ฐ์ดํธ์ ์์๊ฐ CPU 1 ์์ ๋ง๋ค์ด์ง ์์์ ๋์ผํ
๊ฒ์ด๋ผ๋ ๋ณด์ฅ์ด ์์ต๋๋ค.
์ฌ๊ธฐ์ ๊ฐ์
ํ๊ธฐ ์ํด์ , ๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๋ ์ฝ๊ธฐ ๋ฐฐ๋ฆฌ์ด๋ฅผ ๋ก๋ ์คํผ๋ ์ด์
๋ค
์ฌ์ด์ ๋ฃ์ด์ผ ํฉ๋๋ค. ์ด๋ ๊ฒ ํจ์ผ๋ก์จ ์บ์๊ฐ ๋ค์ ์์ฒญ์ ์ฒ๋ฆฌํ๊ธฐ ์ ์ ์ผ๊ด์ฑ
ํ๋ฅผ ์ฒ๋ฆฌํ๋๋ก ๊ฐ์ ํ๊ฒ ๋ฉ๋๋ค.
CPU 1 CPU 2 COMMENT
=============== =============== =======================================
u == 0, v == 1 and p == &u, q == &u
v = 2;
smp_wmb();
<A:modify v=2> <C:busy>
<C:queue v=2>
p = &v; q = p;
<D:request p>
<B:modify p=&v> <D:commit p=&v>
<D:read p>
smp_read_barrier_depends()
<C:unbusy>
<C:commit v=2>
x = *q;
<C:read *q> ์บ์์ ์
๋ฐ์ดํธ ๋ v ๋ฅผ ์ฝ์
์ด๋ฐ ๋ถ๋ฅ์ ๋ฌธ์ ๋ DEC Alpha ๊ณ์ด ํ๋ก์ธ์๋ค์์ ๋ฐ๊ฒฌ๋ ์ ์๋๋ฐ, ์ด๋ค์
๋ฐ์ดํฐ ๋ฒ์ค๋ฅผ ์ข ๋ ์ ์ฌ์ฉํด ์ฑ๋ฅ์ ๊ฐ์ ํ ์ ์๋, ๋ถํ ๋ ์บ์๋ฅผ ๊ฐ์ง๊ณ ์๊ธฐ
๋๋ฌธ์
๋๋ค. ๋๋ถ๋ถ์ CPU ๋ ํ๋์ ์ฝ๊ธฐ ์คํผ๋ ์ด์
์ ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค๊ฐ ๋ค๋ฅธ ์ฝ๊ธฐ
์คํผ๋ ์ด์
์ ์์กด์ ์ด๋ผ๋ฉด ๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๋ฅผ ๋ดํฌ์ํต๋๋ค๋ง, ๋ชจ๋๊ฐ ๊ทธ๋ฐ๊ฑด
์๋๊ธฐ ๋๋ฌธ์ ์ด์ ์ ์์กดํด์ ์๋ฉ๋๋ค.
๋ค๋ฅธ CPU ๋ค๋ ๋ถํ ๋ ์บ์๋ฅผ ๊ฐ์ง๊ณ ์์ ์ ์์ง๋ง, ๊ทธ๋ฐ CPU ๋ค์ ํ๋ฒํ ๋ฉ๋ชจ๋ฆฌ
์ก์ธ์ค๋ฅผ ์ํด์๋ ์ด ๋ถํ ๋ ์บ์๋ค ์ฌ์ด์ ์กฐ์ ์ ํด์ผ๋ง ํฉ๋๋ค. Alpha ๋ ๊ฐ์ฅ
์ฝํ ๋ฉ๋ชจ๋ฆฌ ์์ ์๋งจํฑ (semantic) ์ ์ ํํจ์ผ๋ก์จ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๊ฐ ๋ช
์์ ์ผ๋ก
์ฌ์ฉ๋์ง ์์์ ๋์๋ ๊ทธ๋ฐ ์กฐ์ ์ด ํ์ํ์ง ์๊ฒ ํ์ต๋๋ค.
์บ์ ์ผ๊ด์ฑ VS DMA
------------------
๋ชจ๋ ์์คํ
์ด DMA ๋ฅผ ํ๋ ๋๋ฐ์ด์ค์ ๋ํด์๊น์ง ์บ์ ์ผ๊ด์ฑ์ ์ ์งํ์ง๋
์์ต๋๋ค. ๊ทธ๋ฐ ๊ฒฝ์ฐ, DMA ๋ฅผ ์๋ํ๋ ๋๋ฐ์ด์ค๋ RAM ์ผ๋ก๋ถํฐ ์๋ชป๋ ๋ฐ์ดํฐ๋ฅผ
์ฝ์ ์ ์๋๋ฐ, ๋ํฐ ์บ์ ๋ผ์ธ์ด CPU ์ ์บ์์ ๋จธ๋ฌด๋ฅด๊ณ ์๊ณ , ๋ฐ๋ ๊ฐ์ด ์์ง
RAM ์ ์จ์ง์ง ์์์ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์ , ์ปค๋์
์ ์ ํ ๋ถ๋ถ์์ ๊ฐ CPU ์บ์์ ๋ฌธ์ ๋๋ ๋นํธ๋ค์ ํ๋ฌ์ (flush) ์์ผ์ผ๋ง ํฉ๋๋ค
(๊ทธ๋ฆฌ๊ณ ๊ทธ๊ฒ๋ค์ ๋ฌดํจํ - invalidation - ์ํฌ ์๋ ์๊ฒ ์ฃ ).
๋ํ, ๋๋ฐ์ด์ค์ ์ํด RAM ์ DMA ๋ก ์ฐ์ฌ์ง ๊ฐ์ ๋๋ฐ์ด์ค๊ฐ ์ฐ๊ธฐ๋ฅผ ์๋ฃํ ํ์
CPU ์ ์บ์์์ RAM ์ผ๋ก ์ฐ์ฌ์ง๋ ๋ํฐ ์บ์ ๋ผ์ธ์ ์ํด ๋ฎ์ด์จ์ง ์๋ ์๊ณ , CPU
์ ์บ์์ ์กด์ฌํ๋ ์บ์ ๋ผ์ธ์ด ํด๋น ์บ์์์ ์ญ์ ๋๊ณ ๋ค์ ๊ฐ์ ์ฝ์ด๋ค์ด๊ธฐ
์ ๊น์ง๋ RAM ์ด ์
๋ฐ์ดํธ ๋์๋ค๋ ์ฌ์ค ์์ฒด๊ฐ ์จ๊ฒจ์ ธ ๋ฒ๋ฆด ์๋ ์์ต๋๋ค. ์ด
๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์ , ์ปค๋์ ์ ์ ํ ๋ถ๋ถ์์ ๊ฐ CPU ์ ์บ์ ์์ ๋ฌธ์ ๊ฐ ๋๋
๋นํธ๋ค์ ๋ฌดํจํ ์์ผ์ผ ํฉ๋๋ค.
์บ์ ๊ด๋ฆฌ์ ๋ํ ๋ ๋ง์ ์ ๋ณด๋ฅผ ์ํด์ Documentation/cachetlb.txt ๋ฅผ
์ฐธ๊ณ ํ์ธ์.
์บ์ ์ผ๊ด์ฑ VS MMIO
-------------------
Memory mapped I/O ๋ ์ผ๋ฐ์ ์ผ๋ก CPU ์ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ ๋ด์ ํ ์๋์ฐ์ ํน์ ๋ถ๋ถ
๋ด์ ๋ฉ๋ชจ๋ฆฌ ์ง์ญ์ ์ด๋ฃจ์ด์ง๋๋ฐ, ์ด ์๋์ฐ๋ ์ผ๋ฐ์ ์ธ, RAM ์ผ๋ก ํฅํ๋
์๋์ฐ์๋ ๋ค๋ฅธ ํน์ฑ์ ๊ฐ์ต๋๋ค.
๊ทธ๋ฐ ํน์ฑ ๊ฐ์ด๋ฐ ํ๋๋, ์ผ๋ฐ์ ์ผ๋ก ๊ทธ๋ฐ ์ก์ธ์ค๋ ์บ์๋ฅผ ์์ ํ ์ฐํํ๊ณ
๋๋ฐ์ด์ค ๋ฒ์ค๋ก ๊ณง๋ฐ๋ก ํฅํ๋ค๋ ๊ฒ์
๋๋ค. ์ด ๋ง์ MMIO ์ก์ธ์ค๋ ๋จผ์
์์๋์ด์ ์บ์์์ ์๋ฃ๋ ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค๋ฅผ ์ถ์ํ ์ ์๋ค๋ ๋ป์
๋๋ค. ์ด๋ฐ
๊ฒฝ์ฐ์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ง์ผ๋ก๋ ์ถฉ๋ถ์น ์๊ณ , ๋ง์ฝ ์บ์๋ ๋ฉ๋ชจ๋ฆฌ ์ฐ๊ธฐ ์คํผ๋ ์ด์
๊ณผ
MMIO ์ก์ธ์ค๊ฐ ์ด๋ค ๋ฐฉ์์ผ๋ก๋ ์์กด์ ์ด๋ผ๋ฉด ํด๋น ์บ์๋ ๋ ์คํผ๋ ์ด์
์ฌ์ด์
๋น์์ ธ(flush)์ผ๋ง ํฉ๋๋ค.
======================
CPU ๋ค์ด ์ ์ง๋ฅด๋ ์ผ๋ค
======================
ํ๋ก๊ทธ๋๋จธ๋ CPU ๊ฐ ๋ฉ๋ชจ๋ฆฌ ์คํผ๋ ์ด์
๋ค์ ์ ํํ ์์ฒญํ๋๋ก ์ํํด ์ค ๊ฒ์ด๋ผ๊ณ
์๊ฐํ๋๋ฐ, ์๋ฅผ ๋ค์ด ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ฅผ CPU ์๊ฒ ๋๊ธด๋ค๋ฉด:
a = READ_ONCE(*A);
WRITE_ONCE(*B, b);
c = READ_ONCE(*C);
d = READ_ONCE(*D);
WRITE_ONCE(*E, e);
CPU ๋ ๋ค์ ์ธ์คํธ๋ญ์
์ ์ฒ๋ฆฌํ๊ธฐ ์ ์ ํ์ฌ์ ์ธ์คํธ๋ญ์
์ ์ํ ๋ฉ๋ชจ๋ฆฌ
์คํผ๋ ์ด์
์ ์๋ฃํ ๊ฒ์ด๋ผ ์๊ฐํ๊ณ , ๋ฐ๋ผ์ ์์คํ
์ธ๋ถ์์ ๊ด์ฐฐํ๊ธฐ์๋ ์ ํด์ง
์์๋๋ก ์คํผ๋ ์ด์
์ด ์ํ๋ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค:
LOAD *A, STORE *B, LOAD *C, LOAD *D, STORE *E.
๋น์ฐํ์ง๋ง, ์ค์ ๋ก๋ ํจ์ฌ ์๋ง์
๋๋ค. ๋ง์ CPU ์ ์ปดํ์ผ๋ฌ์์ ์์ ๊ฐ์ ์
์ฑ๋ฆฝํ์ง ๋ชปํ๋๋ฐ ๊ทธ ์ด์ ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
(*) ๋ก๋ ์คํผ๋ ์ด์
๋ค์ ์คํ์ ๊ณ์ ํด๋๊ฐ๊ธฐ ์ํด ๊ณง๋ฐ๋ก ์๋ฃ๋ ํ์๊ฐ ์๋
๊ฒฝ์ฐ๊ฐ ๋ง์ ๋ฐ๋ฉด, ์คํ ์ด ์คํผ๋ ์ด์
๋ค์ ์ข
์ข
๋ณ๋ค๋ฅธ ๋ฌธ์ ์์ด ์ ์๋ ์
์์ต๋๋ค;
(*) ๋ก๋ ์คํผ๋ ์ด์
๋ค์ ์์ธก์ ์ผ๋ก ์ํ๋ ์ ์์ผ๋ฉฐ, ํ์์๋ ๋ก๋์๋ค๊ณ
์ฆ๋ช
๋ ์์ธก์ ๋ก๋์ ๊ฒฐ๊ณผ๋ ๋ฒ๋ ค์ง๋๋ค;
(*) ๋ก๋ ์คํผ๋ ์ด์
๋ค์ ์์ธก์ ์ผ๋ก ์ํ๋ ์ ์์ผ๋ฏ๋ก, ์์๋ ์ด๋ฒคํธ์
์ํ์ค์ ๋ค๋ฅธ ์๊ฐ์ ๋ก๋๊ฐ ์ด๋ค์ง ์ ์์ต๋๋ค;
(*) ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค ์์๋ CPU ๋ฒ์ค์ ์บ์๋ฅผ ์ข ๋ ์ ์ฌ์ฉํ ์ ์๋๋ก ์ฌ๋ฐฐ์น
๋ ์ ์์ต๋๋ค;
(*) ๋ก๋์ ์คํ ์ด๋ ์ธ์ ํ ์์น์์ ์ก์ธ์ค๋ค์ ์ผ๊ด์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์๋
๋ฉ๋ชจ๋ฆฌ๋ I/O ํ๋์จ์ด (๋ฉ๋ชจ๋ฆฌ์ PCI ๋๋ฐ์ด์ค ๋ ๋ค ์ด๊ฒ ๊ฐ๋ฅํ ์
์์ต๋๋ค) ์ ๋ํด ์์ฒญ๋๋ ๊ฒฝ์ฐ, ๊ฐ๋ณ ์คํผ๋ ์ด์
์ ์ํ ํธ๋์ญ์
์ค์
๋น์ฉ์ ์๋ผ๊ธฐ ์ํด ์กฐํฉ๋์ด ์คํ๋ ์ ์์ต๋๋ค; ๊ทธ๋ฆฌ๊ณ
(*) ํด๋น CPU ์ ๋ฐ์ดํฐ ์บ์๊ฐ ์์์ ์ํฅ์ ๋ผ์น ์๋ ์๊ณ , ์บ์ ์ผ๊ด์ฑ
๋ฉ์ปค๋์ฆ์ด - ์คํ ์ด๊ฐ ์ค์ ๋ก ์บ์์ ๋๋ฌํ๋ค๋ฉด - ์ด ๋ฌธ์ ๋ฅผ ์ํ์ํฌ ์๋
์์ง๋ง ์ด ์ผ๊ด์ฑ ๊ด๋ฆฌ๊ฐ ๋ค๋ฅธ CPU ๋ค์๋ ๊ฐ์ ์์๋ก ์ ๋ฌ๋๋ค๋ ๋ณด์ฅ์
์์ต๋๋ค.
๋ฐ๋ผ์, ์์ ์ฝ๋์ ๋ํด ๋ค๋ฅธ CPU ๊ฐ ๋ณด๋ ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ์ ์ ์์ต๋๋ค:
LOAD *A, ..., LOAD {*C,*D}, STORE *E, STORE *B
("LOAD {*C,*D}" ๋ ์กฐํฉ๋ ๋ก๋์
๋๋ค)
ํ์ง๋ง, CPU ๋ ์ค์ค๋ก๋ ์ผ๊ด์ ์ผ ๊ฒ์ ๋ณด์ฅํฉ๋๋ค: CPU _์์ _ ์ ์ก์ธ์ค๋ค์
์์ ์๊ฒ๋ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๊ฐ ์์์๋ ๋ถ๊ตฌํ๊ณ ์ ํํ ์์ ์ธ์์ง ๊ฒ์ผ๋ก ๋ณด์ฌ์ง
๊ฒ์
๋๋ค. ์๋ฅผ ๋ค์ด ๋ค์์ ์ฝ๋๊ฐ ์ฃผ์ด์ก๋ค๋ฉด:
U = READ_ONCE(*A);
WRITE_ONCE(*A, V);
WRITE_ONCE(*A, W);
X = READ_ONCE(*A);
WRITE_ONCE(*A, Y);
Z = READ_ONCE(*A);
๊ทธ๋ฆฌ๊ณ ์ธ๋ถ์ ์ํฅ์ ์ํ ๊ฐ์ญ์ด ์๋ค๊ณ ๊ฐ์ ํ๋ฉด, ์ต์ข
๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ์ด
๋ํ๋ ๊ฒ์ด๋ผ๊ณ ์์๋ ์ ์์ต๋๋ค:
U == *A ์ ์ต์ด ๊ฐ
X == W
Z == Y
*A == Y
์์ ์ฝ๋๋ CPU ๊ฐ ๋ค์์ ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค ์ํ์ค๋ฅผ ๋ง๋ค๋๋ก ํ ๊ฒ๋๋ค:
U=LOAD *A, STORE *A=V, STORE *A=W, X=LOAD *A, STORE *A=Y, Z=LOAD *A
ํ์ง๋ง, ๋ณ๋ค๋ฅธ ๊ฐ์
์ด ์๊ณ ํ๋ก๊ทธ๋จ์ ์์ผ์ ์ด ์ธ์์ด ์ฌ์ ํ ์ผ๊ด์ ์ด๋ผ๊ณ
๋ณด์ธ๋ค๋ ๋ณด์ฅ๋ง ์ง์ผ์ง๋ค๋ฉด ์ด ์ํ์ค๋ ์ด๋ค ์กฐํฉ์ผ๋ก๋ ์ฌ๊ตฌ์ฑ๋ ์ ์์ผ๋ฉฐ, ๊ฐ
์ก์ธ์ค๋ค์ ํฉ์ณ์ง๊ฑฐ๋ ๋ฒ๋ ค์ง ์ ์์ต๋๋ค. ์ผ๋ถ ์ํคํ
์ณ์์ CPU ๋ ๊ฐ์ ์์น์
๋ํ ์ฐ์์ ์ธ ๋ก๋ ์คํผ๋ ์ด์
๋ค์ ์ฌ๋ฐฐ์น ํ ์ ์๊ธฐ ๋๋ฌธ์ ์์ ์์์์
READ_ONCE() ์ WRITE_ONCE() ๋ ๋ฐ๋์ ์กด์ฌํด์ผ ํจ์ ์์๋์ธ์. ๊ทธ๋ฐ ์ข
๋ฅ์
์ํคํ
์ณ์์ READ_ONCE() ์ WRITE_ONCE() ๋ ์ด ๋ฌธ์ ๋ฅผ ๋ง๊ธฐ ์ํด ํ์ํ ์ผ์
๋ญ๊ฐ ๋๋ ์ง ํ๊ฒ ๋๋๋ฐ, ์๋ฅผ ๋ค์ด Itanium ์์๋ READ_ONCE() ์ WRITE_ONCE()
๊ฐ ์ฌ์ฉํ๋ volatile ์บ์คํ
์ GCC ๊ฐ ๊ทธ๋ฐ ์ฌ๋ฐฐ์น๋ฅผ ๋ฐฉ์งํ๋ ํน์ ์ธ์คํธ๋ญ์
์ธ
ld.acq ์ stl.rel ์ธ์คํธ๋ญ์
์ ๊ฐ๊ฐ ๋ง๋ค์ด ๋ด๋๋ก ํฉ๋๋ค.
์ปดํ์ผ๋ฌ ์ญ์ ์ด ์ํ์ค์ ์ก์ธ์ค๋ค์ CPU ๊ฐ ๋ณด๊ธฐ๋ ์ ์ ํฉ์น๊ฑฐ๋ ๋ฒ๋ฆฌ๊ฑฐ๋ ๋ค๋ก
๋ฏธ๋ค๋ฒ๋ฆด ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด:
*A = V;
*A = W;
๋ ๋ค์๊ณผ ๊ฐ์ด ๋ณํ๋ ์ ์์ต๋๋ค:
*A = W;
๋ฐ๋ผ์, ์ฐ๊ธฐ ๋ฐฐ๋ฆฌ์ด๋ WRITE_ONCE() ๊ฐ ์๋ค๋ฉด *A ๋ก์ V ๊ฐ์ ์ ์ฅ์ ํจ๊ณผ๋
์ฌ๋ผ์ง๋ค๊ณ ๊ฐ์ ๋ ์ ์์ต๋๋ค. ๋น์ทํ๊ฒ:
*A = Y;
Z = *A;
๋, ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ READ_ONCE() ์ WRITE_ONCE() ์์ด๋ ๋ค์๊ณผ ๊ฐ์ด ๋ณํ๋ ์
์์ต๋๋ค:
*A = Y;
Z = Y;
๊ทธ๋ฆฌ๊ณ ์ด LOAD ์คํผ๋ ์ด์
์ CPU ๋ฐ๊นฅ์๋ ์์ ๋ณด์ด์ง ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ , ALPHA ๊ฐ ์๋ค
---------------------
DEC Alpha CPU ๋ ๊ฐ์ฅ ์ํ๋ ๋ฉ๋ชจ๋ฆฌ ์์์ CPU ์ค ํ๋์
๋๋ค. ๋ฟ๋ง ์๋๋ผ,
Alpha CPU ์ ์ผ๋ถ ๋ฒ์ ์ ๋ถํ ๋ ๋ฐ์ดํฐ ์บ์๋ฅผ ๊ฐ์ง๊ณ ์์ด์, ์๋ฏธ์ ์ผ๋ก
๊ด๊ณ๋์ด ์๋ ๋๊ฐ์ ์บ์ ๋ผ์ธ์ด ์๋ก ๋ค๋ฅธ ์๊ฐ์ ์
๋ฐ์ดํธ ๋๋๊ฒ ๊ฐ๋ฅํฉ๋๋ค.
์ด๊ฒ ๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๊ฐ ์ ๋ง ํ์ํด์ง๋ ๋ถ๋ถ์ธ๋ฐ, ๋ฐ์ดํฐ ์์กด์ฑ ๋ฐฐ๋ฆฌ์ด๋
๋ฉ๋ชจ๋ฆฌ ์ผ๊ด์ฑ ์์คํ
๊ณผ ํจ๊ป ๋๊ฐ์ ์บ์๋ฅผ ๋๊ธฐํ ์์ผ์, ํฌ์ธํฐ ๋ณ๊ฒฝ๊ณผ ์๋ก์ด
๋ฐ์ดํฐ์ ๋ฐ๊ฒฌ์ ์ฌ๋ฐ๋ฅธ ์์๋ก ์ผ์ด๋๊ฒ ํ๊ธฐ ๋๋ฌธ์
๋๋ค.
๋ฆฌ๋
์ค ์ปค๋์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด ๋ชจ๋ธ์ Alpha ์ ๊ธฐ์ดํด์ ์ ์๋์์ต๋๋ค.
์์ "์บ์ ์ผ๊ด์ฑ" ์๋ธ์น์
์ ์ฐธ๊ณ ํ์ธ์.
๊ฐ์ ๋จธ์ ๊ฒ์คํธ
----------------
๊ฐ์ ๋จธ์ ์์ ๋์ํ๋ ๊ฒ์คํธ๋ค์ ๊ฒ์คํธ ์์ฒด๋ SMP ์ง์ ์์ด ์ปดํ์ผ ๋์๋ค
ํด๋ SMP ์ํฅ์ ๋ฐ์ ์ ์์ต๋๋ค. ์ด๊ฑด UP ์ปค๋์ ์ฌ์ฉํ๋ฉด์ SMP ํธ์คํธ์
๊ฒฐ๋ถ๋์ด ๋ฐ์ํ๋ ๋ถ์์ฉ์
๋๋ค. ์ด ๊ฒฝ์ฐ์๋ mandatory ๋ฐฐ๋ฆฌ์ด๋ฅผ ์ฌ์ฉํด์ ๋ฌธ์ ๋ฅผ
ํด๊ฒฐํ ์ ์๊ฒ ์ง๋ง ๊ทธ๋ฐ ํด๊ฒฐ์ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ์ต์ ์ ํด๊ฒฐ์ฑ
์ด ์๋๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ์๋ฒฝํ๊ฒ ํด๊ฒฐํ๊ธฐ ์ํด, ๋ก์ฐ ๋ ๋ฒจ์ virt_mb() ๋ฑ์ ๋งคํฌ๋ก๋ฅผ ์ฌ์ฉํ ์
์์ต๋๋ค. ์ด๊ฒ๋ค์ SMP ๊ฐ ํ์ฑํ ๋์ด ์๋ค๋ฉด smp_mb() ๋ฑ๊ณผ ๋์ผํ ํจ๊ณผ๋ฅผ
๊ฐ์ต๋๋ค๋ง, SMP ์ SMP ์๋ ์์คํ
๋ชจ๋์ ๋ํด ๋์ผํ ์ฝ๋๋ฅผ ๋ง๋ค์ด๋
๋๋ค.
์๋ฅผ ๋ค์ด, ๊ฐ์ ๋จธ์ ๊ฒ์คํธ๋ค์ (SMP ์ผ ์ ์๋) ํธ์คํธ์ ๋๊ธฐํ๋ฅผ ํ ๋์๋
smp_mb() ๊ฐ ์๋๋ผ virt_mb() ๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
์ด๊ฒ๋ค์ smp_mb() ๋ฅ์ ๊ฒ๋ค๊ณผ ๋ชจ๋ ๋ถ๋ถ์์ ๋์ผํ๋ฉฐ, ํนํ, MMIO ์ ์ํฅ์
๋ํด์๋ ๊ฐ์ฌํ์ง ์์ต๋๋ค: MMIO ์ ์ํฅ์ ์ ์ดํ๋ ค๋ฉด, mandatory ๋ฐฐ๋ฆฌ์ด๋ฅผ
์ฌ์ฉํ์๊ธฐ ๋ฐ๋๋๋ค.
=======
์ฌ์ฉ ์
=======
์ํ์ ๋ฒํผ
-----------
๋ฉ๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์ด๋ ์ํ์ ๋ฒํผ๋ฅผ ์์ฑ์(producer)์ ์๋น์(consumer) ์ฌ์ด์
๋๊ธฐํ์ ๋ฝ์ ์ฌ์ฉํ์ง ์๊ณ ๊ตฌํํ๋๋ฐ์ ์ฌ์ฉ๋ ์ ์์ต๋๋ค. ๋ ์์ธํ ๋ด์ฉ์
์ํด์ ๋ค์์ ์ฐธ๊ณ ํ์ธ์:
Documentation/circular-buffers.txt
=========
์ฐธ๊ณ ๋ฌธํ
=========
Alpha AXP Architecture Reference Manual, Second Edition (Sites & Witek,
Digital Press)
Chapter 5.2: Physical Address Space Characteristics
Chapter 5.4: Caches and Write Buffers
Chapter 5.5: Data Sharing
Chapter 5.6: Read/Write Ordering
AMD64 Architecture Programmer's Manual Volume 2: System Programming
Chapter 7.1: Memory-Access Ordering
Chapter 7.4: Buffering and Combining Memory Writes
IA-32 Intel Architecture Software Developer's Manual, Volume 3:
System Programming Guide
Chapter 7.1: Locked Atomic Operations
Chapter 7.2: Memory Ordering
Chapter 7.4: Serializing Instructions
The SPARC Architecture Manual, Version 9
Chapter 8: Memory Models
Appendix D: Formal Specification of the Memory Models
Appendix J: Programming with the Memory Models
UltraSPARC Programmer Reference Manual
Chapter 5: Memory Accesses and Cacheability
Chapter 15: Sparc-V9 Memory Models
UltraSPARC III Cu User's Manual
Chapter 9: Memory Models
UltraSPARC IIIi Processor User's Manual
Chapter 8: Memory Models
UltraSPARC Architecture 2005
Chapter 9: Memory
Appendix D: Formal Specifications of the Memory Models
UltraSPARC T1 Supplement to the UltraSPARC Architecture 2005
Chapter 8: Memory Models
Appendix F: Caches and Cache Coherency
Solaris Internals, Core Kernel Architecture, p63-68:
Chapter 3.3: Hardware Considerations for Locks and
Synchronization
Unix Systems for Modern Architectures, Symmetric Multiprocessing and Caching
for Kernel Programmers:
Chapter 13: Other Memory Models
Intel Itanium Architecture Software Developer's Manual: Volume 1:
Section 2.6: Speculation
Section 4.4: Memory Access