membarrier(2) - wariua/manpages-ko GitHub Wiki
membarrier - μ€λ λ μ§ν©μ λ©λͺ¨λ¦¬ λ°°λ¦¬μ΄ μ£ΌκΈ°
#include <linux/membarrier.h>
int membarrier(int cmd, int flags);
membarrier()
μμ€ν
νΈμΆμ λ€μ€ μ½μ΄ μμ€ν
μμ λ©λͺ¨λ¦¬ μ κ·Ό μμ μ μ΄μ νμν λ©λͺ¨λ¦¬ λ°°λ¦¬μ΄ μΈμ€νΈλμ
μ μ€λ²ν€λλ₯Ό μ€μΌ μ μκ² ν΄ μ€λ€. νμ§λ§ μ΄ μμ€ν
νΈμΆμ΄ λ©λͺ¨λ¦¬ 배리μ΄λ³΄λ€ 무거μ°λ©°, κ·Έλμ ν¨κ³Όμ μΌλ‘ μ΄μ©νλ €λ©΄ λ©λͺ¨λ¦¬ 배리μ΄λ₯Ό μ΄ μμ€ν
νΈμΆλ‘ κ΅μ²΄νκΈ°λ§ νλ©΄ λλ κ²μ΄ μλλΌ μλ μΈλΆ λ΄μ©μ λν μ΄ν΄κ° νμνλ€.
λ©λͺ¨λ¦¬ 배리μ΄λ₯Ό μ¬μ©ν λ κ³ λ €ν΄μΌ νλ κ²μ λ©λͺ¨λ¦¬ 배리μ΄μ νμ μλκ° λλ λ©λͺ¨λ¦¬ λ°°λ¦¬μ΄ μ§μ΄ μμ΄μΌ ν μλ μκ³ , μν€ν μ² λ©λͺ¨λ¦¬ λͺ¨λΈμμ κ·Έλ° λμ 배리μ΄λ₯Ό μꡬνμ§ μμ μλ μλ€λ μ μ΄λ€.
λμ λ°°λ¦¬μ΄ μ€ νμͺ½(μ΄ν "λΉ λ₯Έ μͺ½")μ΄ λ€λ₯Έ μͺ½(μ΄ν "λλ¦° μͺ½")λ³΄λ€ ν¨μ¬ μμ£Ό μ€νλλ κ²½μ°κ° μλ€. κ·Έλ° κ²½μ°κ° membarrier()
λ₯Ό μ¬μ©ν μ£Όμ λμμ΄λ€. ν΅μ¬ μμ΄λμ΄λ κ·Έλ° λμ 배리μ΄μμ λΉ λ₯Έ μͺ½ λ©λͺ¨λ¦¬ 배리μ΄λ₯Ό λ€μκ³Ό κ°μ λ¨μ μ»΄νμΌλ¬ 배리μ΄λ‘ κ΅μ²΄νκ³ λλ¦° μͺ½ λ©λͺ¨λ¦¬ 배리μ΄λ₯Ό membarrier()
νΈμΆλ‘ κ΅μ²΄νλ κ²μ΄λ€.
asm volatile ("" : : : "memory")
κ·Έλ¬λ©΄ λλ¦° μͺ½μ μ€λ²ν€λλ₯Ό λνκ³ λΉ λ₯Έ μͺ½μμ μ€λ²ν€λλ₯Ό μμ κ² λμ΄ membarrier()
νΈμΆ μ€λ²ν€λκ° λΉ λ₯Έ μͺ½ μ±λ₯ μ΄λμ μννμ§ μμ λ§νΌ λλ¦° μͺ½μ΄ λλ¬ΌκΈ°λ§ νλ€λ©΄ κ²°κ³Όμ μΌλ‘ μ 체 μ±λ₯μ΄ μ¬λΌκ°κ² λλ€.
cmd
μΈμλ λ€μ μ€ νλμ΄λ€.
-
MEMBARRIER_CMD_QUERY
(리λ μ€ 4.3λΆν°) - μ§μ λͺ
λ Ή μ§ν©μ μ§μνλ€. νΈμΆ λ°ν κ°μ μ§μ λͺ
λ Ήλ€μ λΉνΈ λ§μ€ν¬μ΄λ€.
MEMBARRIER_CMD_QUERY
μ κ°μ 0μ΄λ―λ‘ κ·Έ λΉνΈ λ§μ€ν¬μ ν¬ν¨λμ§ μλλ€. (membarrier()
λ₯Ό μ 곡νλ 컀λμμ) μ΄ λͺ λ Ήμ νμ μ§μνλ€. -
MEMBARRIER_CMD_GLOBAL
(리λ μ€ 4.16λΆν°) -
membarrier()
μμ€ν νΈμΆ μ§μ κ³Ό λ°ν μ¬μ΄μμ μμ€ν μμ λͺ¨λ νλ‘μΈμ€μ μ€λ λ λͺ¨λκ° μ¬μ©μ κ³΅κ° μ£Όμμ λν λͺ¨λ λ©λͺ¨λ¦¬ μ κ·Όμ΄ νλ‘κ·Έλ¨ μμμ μΌμΉνλ μνλ₯Ό κ±°μΉλλ‘ νλ€. μ΄ λͺ λ Ήμ μμ€ν μ μ€λ λ λͺ¨λλ₯Ό λμμΌλ‘ νλ€. -
MEMBARRIER_CMD_GLOBAL_EXPEDITED
(리λ μ€ 4.16λΆν°) -
MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED
λ‘ λ―Έλ¦¬ λ±λ‘ν νλ‘μΈμ€ λͺ¨λμ μ€ν μ€μΈ μ€λ λ λͺ¨λμμ λ©λͺ¨λ¦¬ 배리μ΄λ₯Ό μ€ννλ€.μμ€ν νΈμΆ λ°ν μμ, μ€ν μ€μΈ μ€λ λ λͺ¨λκ° μ¬μ©μ κ³΅κ° μ£Όμμ λν λͺ¨λ λ©λͺ¨λ¦¬ μ κ·Όμ΄ νλ‘κ·Έλ¨ μμμ μΌμΉνλ μνλ₯Ό μμ€ν νΈμΆ μ§μ κ³Ό λ°ν μ¬μ΄μμ κ±°μ³€λ€λ 보μ₯μ νΈμΆ μ€λ λκ° μ»κ² λλ€. (μ€ν μ€μ΄ μλ μ€λ λλ μ€μ§μ μΌλ‘ κ·Έλ° μνμ μλ κ²μ΄λ€.)
MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED
λ‘ λ―Έλ¦¬ λ±λ‘ν νλ‘μΈμ€μ μ€λ λμ λν΄μλ§ λ³΄μ₯μ΄ μ΄λ€μ§λ€.λ±λ‘μ 배리μ΄λ₯Ό λ°μλ€μ΄κ² λ€λ μλμ λν κ²μ΄λ―λ‘
MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED
λ₯Ό μ΄ μ μλ νλ‘μΈμ€μμMEMBARRIER_CMD_GLOBAL_EXPEDITED
λ₯Ό νΈμΆνλ κ²μ΄ μ ν¨νλ€."μ μ μ²λ¦¬(expedited)" λͺ λ Ήμ κ·Έλ μ§ μμ λͺ λ Ήλ³΄λ€ λΉ¨λ¦¬ μλ£λλ€. μ λ λΈλ‘ νμ§ μλλ€. νμ§λ§ μΆκ° μ€λ²ν€λλ₯Ό μ λ°νλ λ¨μ μ΄ μλ€.
-
MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED
(리λ μ€ 4.16λΆν°) -
MEMBARRIER_CMD_GLOBAL_EXPEDITED
λ©λͺ¨λ¦¬ 배리μ΄λ₯Ό λ°μλ€μ΄λ €λ νλ‘μΈμ€μ μλλ₯Ό μλ¦°λ€. -
MEMBARRIER_CMD_PRIVATE_EXPEDITED
(리λ μ€ 4.14λΆν°) -
νΈμΆ μ€λ λμ κ°μ νλ‘μΈμ€μ μν μ€ν μ€μΈ μ€λ λ κ°κ°μμ λ©λͺ¨λ¦¬ 배리μ΄λ₯Ό μ€ννλ€.
μμ€ν νΈμΆ λ°ν μμ, μ€ν μ€μΈ νμ μλ§€ μ€λ λ λͺ¨λκ° μ¬μ©μ κ³΅κ° μ£Όμμ λν λͺ¨λ λ©λͺ¨λ¦¬ μ κ·Όμ΄ νλ‘κ·Έλ¨ μμμ μΌμΉνλ μνλ₯Ό μμ€ν νΈμΆ μ§μ κ³Ό λ°ν μ¬μ΄μμ κ±°μ³€λ€λ 보μ₯μ νΈμΆ μ€λ λκ° μ»κ² λλ€. (μ€ν μ€μ΄ μλ μ€λ λλ μ€μ§μ μΌλ‘ κ·Έλ° μνμ μλ κ²μ΄λ€.) νΈμΆ μ€λ λμ κ°μ νλ‘μΈμ€μ μ€λ λμ λν΄μλ§ λ³΄μ₯μ΄ μ΄λ€μ§λ€.
"μ μ μ²λ¦¬" λͺ λ Ήμ κ·Έλ μ§ μμ λͺ λ Ήλ³΄λ€ λΉ¨λ¦¬ μλ£λλ€. μ λ λΈλ‘ νμ§ μλλ€. νμ§λ§ μΆκ° μ€λ²ν€λλ₯Ό μ λ°νλ λ¨μ μ΄ μλ€.
νλ‘μΈμ€λ³ μ μ μ²λ¦¬ λͺ λ Ήμ μ¬μ©νλ €λ νλ‘μΈμ€λ μ¬μ© μ μ κ·Έ μλλ₯Ό 미리 μλ €μΌ νλ€.
-
MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED
(리λ μ€ 4.14λΆν°) -
MEMBARRIER_CMD_PRIVATE_EXPEDITED
λ₯Ό μ¬μ©νλ €λ νλ‘μΈμ€μ μλλ₯Ό μλ¦°λ€. -
MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE
(리λ μ€ 4.16λΆν°) -
MEMBARRIER_CMD_PRIVATE_EXPEDITED
μμ κΈ°μ ν λ©λͺ¨λ¦¬ μμ 보μ₯μ λν΄μ, μμ€ν νΈμΆ λ°ν μμ μ€ν μ€μΈ νμ μλ§€ μ€λ λ λͺ¨λκ° μ½μ΄ μ§λ ¬ν μΈμ€νΈλμ μ μ€ννλ€λ 보μ₯μ νΈμΆ μ€λ λκ° μ»κ² λλ€. νΈμΆ μ€λ λμ κ°μ νλ‘μΈμ€μ μ€λ λμ λν΄μλ§ μ΄ λ³΄μ₯μ΄ μ΄λ€μ§λ€."μ μ μ²λ¦¬" λͺ λ Ήμ κ·Έλ μ§ μμ λͺ λ Ήλ³΄λ€ λΉ¨λ¦¬ μλ£λλ€. μ λ λΈλ‘ νμ§ μλλ€. νμ§λ§ μΆκ° μ€λ²ν€λλ₯Ό μ λ°νλ λ¨μ μ΄ μλ€.
νλ‘μΈμ€λ³ μ μ μ²λ¦¬ μ½μ΄ λκΈ°ν λͺ λ Ήμ μ¬μ©νλ €λ νλ‘μΈμ€λ μ¬μ© μ μ κ·Έ μλλ₯Ό 미리 μλ €μΌ νλ€.
-
MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE
(리λ μ€ 4.16λΆν°) -
MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE
λ₯Ό μ¬μ©νλ €λ νλ‘μΈμ€μ μλλ₯Ό μλ¦°λ€. -
MEMBARRIER_CMD_SHARED
(리λ μ€ 4.3λΆν°) - ν€λ νμ νΈνμ±μ μν΄ μ‘΄μ¬νλ
MEMBARRIER_CMD_GLOBAL
μ λ³μΉμ΄λ€.
flags
μΈμλ νμ¬ μ¬μ©νμ§ μμΌλ©° 0μΌλ‘ μ§μ ν΄μΌ νλ€.
κ° λμ μ€λ λμμ νλ‘κ·Έλ¨ μμλ‘ μνλλ λͺ¨λ λ©λͺ¨λ¦¬ μ κ·Όμ membarrier()
μ λν΄μ μμκ° μ§μΌμ§λ€κ³ (ordered) 보μ₯λλ€.
λ°°λ¦¬μ΄ μ νλ‘ νλ‘κ·Έλ¨ μμμ λ°λΌ λ©λͺ¨λ¦¬ μ κ·Όμ μννκ² κ°μ νλ μ»΄νμΌλ¬ 배리μ΄λ₯Ό μλ―Έλ‘ μ barrier()
λ‘ λνλ΄κ³ λ°°λ¦¬μ΄ μ νλ‘ μμ ν λ©λͺ¨λ¦¬ μ κ·Ό μμλ₯Ό κ°μ νλ λͺ
μμ λ©λͺ¨λ¦¬ 배리μ΄λ₯Ό smp_mb()
λ‘ λνλΈλ€λ©΄, barrier()
, membarrier()
, smp_mb()
μ κ° μμ λν λ€μ μμ ν
μ΄λΈμ μ»λλ€. Oλ μμκ° μ§μΌμ§λ κ²μ΄κ³ Xλ μμκ° μ§μΌμ§μ§ μλ κ²μ΄λ€.
barrier() |
smp_mb() |
membarrier() |
|
---|---|---|---|
barrier() |
X | X | O |
smp_mb() |
X | O | O |
membarrier() |
O | O | O |
μ±κ³΅ μ MEMBARRIER_CMD_QUERY
λμμ μ§μ λͺ
λ Ήλ€μ λΉνΈ λ§μ€ν¬λ₯Ό λ°ννλ©°, MEMBARRIER_CMD_GLOBAL
, MEMBARRIER_CMD_GLOBAL_EXPEDITED
, MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED
, MEMBARRIER_CMD_PRIVATE_EXPEDITED
, MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED
, MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE
, MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE
λμμ 0μ λ°ννλ€. μ€λ₯ μ -1μ λ°ννλ©° errno
λ₯Ό μ μ ν μ€μ νλ€.
ν λͺ
λ Ήμ λν΄μ flags
λ₯Ό 0μΌλ‘ μ€μ μ μ΄ μμ€ν
νΈμΆμ΄ μ¬λΆν
λκΉμ§ νμ κ°μ κ°μ λ°ννλ€κ³ 보μ₯λλ€. μ¦, κ°μ μΈμλ‘ νλ μ΄ν νΈμΆμ΄ κ°μ κ²°κ³Όλ₯Ό λ³λλ€. λ°λΌμ flags
λ₯Ό 0μΌλ‘ μ€μ μ 첫 λ²μ§Έ membarrier()
νΈμΆμμλ§ μ€λ₯ μ²λ¦¬κ° νμνλ€.
EINVAL
-
cmd
κ° μ ν¨νμ§ μκ±°λ,flags
κ° 0μ΄ μλκ±°λ, CPU λ§€κ°λ³μnohz_full
μ΄ μ€μ λμ΄μMEMBARRIER_CMD_GLOBAL
λͺ λ Ήμ΄ λΉνμ±νλμ΄ μκ±°λ,MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE
λ°MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE
λͺ λ Ήμ΄ μν€ν μ²μ ꡬνλμ΄ μμ§ μλ€. ENOSYS
-
membarrier()
μμ€ν νΈμΆμ΄ μ΄ μ»€λμ ꡬνλμ΄ μμ§ μλ€. EPERM
- νμ¬ νλ‘μΈμ€κ° νλ‘μΈμ€λ³ μ μ μ²λ¦¬ λͺ λ Ή μ¬μ©μ μμ μ κ³ λ₯Ό νμ§ μμλ€.
리λ
μ€ 4.3μμ membarrier()
μμ€ν
νΈμΆμ΄ μΆκ°λμλ€.
membarrier()
λ 리λ
μ€ μ μ©μ΄λ€.
λ©λͺ¨λ¦¬ λͺ¨λΈμ΄ μ½ν μμ(weakly-ordered)μΈ μν€ν μ²μμ μΈμ€νΈλμ μΈνΈμ λ©λͺ¨λ¦¬ λ°°λ¦¬μ΄ μΈμ€νΈλμ μ΄ ν¬ν¨λμ΄ μλ€. λ€λ₯Έ μ½μ΄ μμ λμνλ 배리μ΄μ λν΄μ λ°°λ¦¬μ΄ μ λ©λͺ¨λ¦¬ μ κ·Όκ³Ό λ°°λ¦¬μ΄ ν λ©λͺ¨λ¦¬ μ κ·Όμ μμλ₯Ό μ§μΌ μ€λ€. μλ₯Ό λ€μ΄ μ μ₯ fenceλ‘ μμλ₯Ό μ μ§νλ μ μ₯λ€μ λν΄μ μ μ¬ fenceκ° νμ€ μ μ μ¬μ νμ€ ν μ μ¬μ μμλ₯Ό μ μ§ν μ μλ€.
νλ‘κ·Έλ¨ μμλ νλ‘κ·Έλ¨ μ΄μ λΈλ¦¬ μ½λμμ μΈμ€νΈλμ μ΄ λ°°μΉλλ μμμ΄λ€.
membarrier()
κ° μ μ©ν μ μλ κ²½μ°λ‘ Read-Copy-Update λΌμ΄λΈλ¬λ¦¬λ κ°λΉμ§ 컬λ ν° κ΅¬ν λ±μ΄ μλ€.
"fast_path()
"λ₯Ό λ§€μ° μμ£Ό μ€ννκ³ "slow_path()
"λ₯Ό λλ¬Όκ² μ€ννλ λ€μ€ μ€λ λ μμ©μ κ°μ ν λ λ€μκ³Ό κ°μ (x86μ©) μ½λλ₯Ό membarrier()
λ₯Ό μ°λλ‘ λ³νν μ μλ€.
#include <stdlib.h>
static volatile int a, b;
static void
fast_path(int *read_b)
{
a = 1;
asm volatile ("mfence" : : : "memory");
*read_b = b;
}
static void
slow_path(int *read_a)
{
b = 1;
asm volatile ("mfence" : : : "memory");
*read_a = a;
}
int
main(int argc, char **argv)
{
int read_a, read_b;
/*
* μ€μ μμ©μμλ fast_path()μ slow_path()λ₯Ό
* λ€λ₯Έ μ€λ λμμ νΈμΆνκ² λ¨. μμ νλ‘κ·Έλ¨μ
* μ§§κ² λ§λ€κΈ° μν΄ main()μμ νΈμΆν¨.
*/
slow_path(&read_a);
fast_path(&read_b);
/*
* read_b == 0μ΄λ©΄ read_a == 1μ΄κ³
* read_a == 0μ΄λ©΄ read_b == 1.
*/
if (read_b == 0 && read_a == 0)
abort();
exit(EXIT_SUCCESS);
}
μ μ½λλ₯Ό membarrier()
λ₯Ό μ°λλ‘ λ³ννλ©΄ λ€μμ΄ λλ€.
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/membarrier.h>
static volatile int a, b;
static int
membarrier(int cmd, int flags)
{
return syscall(__NR_membarrier, cmd, flags);
}
static int
init_membarrier(void)
{
int ret;
/* membarrier() μ§μνλμ§ νμΈ */
ret = membarrier(MEMBARRIER_CMD_QUERY, 0);
if (ret < 0) {
perror("membarrier");
return -1;
}
if (!(ret & MEMBARRIER_CMD_GLOBAL)) {
fprintf(stderr,
"membarrier does not support MEMBARRIER_CMD_GLOBAL\n");
return -1;
}
return 0;
}
static void
fast_path(int *read_b)
{
a = 1;
asm volatile ("" : : : "memory");
*read_b = b;
}
static void
slow_path(int *read_a)
{
b = 1;
membarrier(MEMBARRIER_CMD_GLOBAL, 0);
*read_a = a;
}
int
main(int argc, char **argv)
{
int read_a, read_b;
if (init_membarrier())
exit(EXIT_FAILURE);
/*
* μ€μ μμ©μμλ fast_path()μ slow_path()λ₯Ό
* λ€λ₯Έ μ€λ λμμ νΈμΆνκ² λ¨. μμ νλ‘κ·Έλ¨μ
* μ§§κ² λ§λ€κΈ° μν΄ main()μμ νΈμΆν¨.
*/
slow_path(&read_a);
fast_path(&read_b);
/*
* read_b == 0μ΄λ©΄ read_a == 1μ΄κ³
* read_a == 0μ΄λ©΄ read_b == 1.
*/
if (read_b == 0 && read_a == 0)
abort();
exit(EXIT_SUCCESS);
}
2018-04-30