Post

[OS] Operating System(6-2): Mutax lock, Semaphore

[OS] Operating System(6-2): Mutax lock, Semaphore

๐Ÿ€ ์šด์˜์ฒด์ œ ์ „๊ณต ์ˆ˜์—… ์ •๋ฆฌ

์ด์ „์— ๋ณธ ํ•˜๋“œ์›จ์–ด ๊ธฐ๋ฐ˜ ํ•ด๊ฒฐ์ฑ…๋“ค(Test-and-Set,CAS,atomic ๋ณ€์ˆ˜ ๋“ฑ)์€ ๊ฐ•๋ ฅํ•˜์ง€๋งŒ ์ง์ ‘ ์‚ฌ์šฉํ•˜๊ธฐ์—๋Š” ๋ณต์žกํ•˜๊ณ  ์ ‘๊ทผํ•˜๊ธฐ๊ฐ€ ์–ด๋ ต๋‹ค!

๊ทธ๋ž˜์„œ ์ด๋Ÿฌํ•œ ํ•˜๋“œ์›จ์–ด ๊ธฐ๋Šฅ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋” ๋†’์€ ์ˆ˜์ค€์˜ software๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

๊ทธ ์ค‘ ๊ธฐ๋ณธ์ ์ธ ๊ฒƒ์ด Mutex Lock

Mutex Locks


๐Ÿ“šMutex Lock: cs ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ software tool, Mutual Exclusion์˜ ์ค„์ž„๋ง, ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๋‚˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๊ณต์œ  ์ž์›์— ๋™์‹œ์— ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€

  • critical section์„ ๋ณดํ˜ธํ•˜๊ธฐ ์œ„ํ•ด ๋จผ์ € acquire()๋กœ lock์„ ํš๋“, ๋‚˜์ค‘์— release()๋กœ lock์„ ํ•ด์ œ
    • boolean variable์„ ์‚ฌ์šฉํ•˜์—ฌ lock์˜ ๊ฐ€์šฉ์„ฑ์„ ๋‚˜ํƒ€๋ƒ„
  • acquire(), release()๋Š” ์›์ž์ ์œผ๋กœ ๊ตฌํ˜„๋˜์–ด์•ผํ•จ

Mutex Lock์˜ ๊ตฌ์กฐ

1
2
3
4
5
6
while (true) {
    acquire lock
    critical section
    release lock
    remainder section
}

Mutex Lock์˜ ๊ตฌํ˜„

1
2
3
4
5
6
7
8
9
acquire() {
    while (!available)
        ; /* busy wait */
    available = false;
}

release() {
    available = true;
}

์ด ํ•จ์ˆ˜๋“ค์€ ์›์ž์ ์œผ๋กœ ์‹คํ–‰ ๋˜์–ด์•ผํ•จ
โ†’ Test-and-Set, Compare-and-Swap๊ณผ ๊ฐ™์€ ํ•˜๋“œ์›จ์–ด ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•จ

  • Test-and-Set ```c acquire() { while (test_and_set(&lock)) ; /* busy wait */ }

release() { lock = false; }

1
2
3
4
5
6
7
8
9
10
11
* **Compare-and-Swap**
```c
acquire() {
    while (compare_and_swap(&lock, 0, 1) != 0)
        ; /* busy wait */
}

release() {
    lock = 0;
}

์œ„์˜ Mutex lock ๊ตฌํ˜„์—์„œ๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ lock์„ ํš๋“ํ•  ์ˆ˜ ์—†์„ ๋•Œ ๊ณ„์†ํ•ด์„œ CPU๋ฅผ ์†Œ๋น„ํ•˜๋ฉฐ ๋Œ€๊ธฐํ•œ๋‹ค. ์ด๋ฅผ Busy waiting or Spinlock ์ด๋ผ ํ•œ๋‹ค.

โœ…Spinlock ํŠน์ง•:

  • ํ”„๋กœ์„ธ์Šค๊ฐ€ lock์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ ๊ณ„์† CPU๋ฅผ ์†Œ๋น„
  • Context Switching ๋ฐœ์ƒ X
  • lock ๋ณด์œ  ์‹œ๊ฐ„์ด ์งง๊ณ  ๊ฒฝ์Ÿ์ด ์ ์€ ํ™˜๊ฒฝ์—์„œ ํšจ์œจ์ 
  • ๋‹ค์ค‘ ์ฝ”์–ด/ํ”„๋กœ์„ธ์„œ ํ™˜๊ฒฝ์—์„œ ์ ํ•ฉ

๐Ÿ“Spinlock ์œ ๋ฆฌํ•œ ์ƒํ™ฉ:
โ€œlock์„ ๋ณด์œ ํ•˜๋Š” ์‹œ๊ฐ„ < ๋‘ ๊ฐœ์˜ context switching ์‹œ๊ฐ„โ€ ์˜ ๊ฒฝ์šฐ์— Spinlock ์œ ๋ฆฌํ•จ โ†’ lock์„ ์–ป๊ธฐ ์œ„ํ•ด block ๋˜๊ณ  ๋‹ค์‹œ ๊บ ์–ด๋‚˜๋Š” ์˜ค๋ฒ„ํ—ค๋“œ๋ณด๋‹ค ์งง์€ ์‹œ๊ฐ„ ๋™์•ˆ CPU ์†Œ๋น„ํ•˜๋ฉฐ ๋Œ€๊ธฐํ•˜๋Š” ๊ฒƒ์ด ๋” ํšจ์œจ์ ์ด๊ธฐ ๋•Œ๋ฌธ!

Semaphore


๐Ÿ“šSemaphore: Mutex lock๋ณด๋‹ค ๋” ์ •๊ตํ•œ ํ”„๋กœ์„ธ์Šค๊ฐ„ ๋™๊ธฐํ™”๋ฅผ ์ œ๊ณต

  • Semaphore S: integer variable - ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ž์› ์ˆ˜
  • ๋‘ ๊ฐ€์ง€ ์›์ž์  ์—ฐ์‚ฐ:
    • wait(S)=P(): semaphore ๊ฐ’์„ ๊ฐ์†Œ์‹œํ‚ค๊ณ , ๊ฐ’์ด ์Œ์ˆ˜๋ฉด ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ธ”๋ก
    • signal(S)=V(): semaphore ๊ฐ’์„ ์ฆ๊ฐ€์‹œํ‚ค๊ณ , ๋Œ€๊ธฐ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์žˆ์œผ๋ฉด ๊นจ์šด๋‹ค

wait(S) operation

1
2
3
4
5
wait(S) {
    while (S <= 0)
        ; // busy wait
    S--;
}

signal(S) operation

1
2
3
signal(S) {
    S++;
}

Semaphore Usage


semaphore๋Š” ๊ฐ’์˜ ๋ฒ”์œ„์— ๋”ฐ๋ผ ๋‘ ๊ฐ€์ง€ ์œ ํ˜•์œผ๋กœ ๋‚˜๋‰œ๋‹ค.

  1. Binary Semaphore
    • ์„ธ๋งˆํฌ์–ด ๊ฐ’์ด 0๊ณผ 1 ์‚ฌ์ด๋กœ๋งŒ ์ œํ•œ๋จ
    • Mutex lock๊ณผ ๋™์ผํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณต
    • Mutual exclusion๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋จ
    • ์ดˆ๊ธฐ๊ฐ’์€ ๋ณดํ†ต 1๋กœ ์„ค์ •๋˜์–ด, ์ฒซ ๋ฒˆ์งธ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ž์›์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•จ
  2. Counting Semaphore
    • ์„ธ๋งˆํฌ์–ด ๊ฐ’์ด ์ œํ•œ ์—†๋Š” ์˜์—ญ์—์„œ ๋ณ€ํ•  ์ˆ˜ ์žˆ๋‹ค
    • ๋™์‹œ์— ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ž์›์˜ ๊ฐœ์ˆ˜๋ฅผ ์ œ์–ดํ•จ
    • ์˜ˆ๋ฅผ ๋“ค์–ด, 10๋Œ€์˜ ํ”„๋ฆฐํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์„ธ๋งˆํฌ์–ด๋Š” ์ดˆ๊ธฐ๊ฐ’์ด 10์ด ๋  ์ˆ˜ ์žˆ๋‹ค

Semaphore ํ™œ์šฉ ์˜ˆ์ œ

์„ธ๋งˆํฌ์–ด๋ฅผ ํ™œ์šฉํ•ด ํ”„๋กœ์„ธ์Šค ๊ฐ„ ๋™๊ธฐํ™” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ์˜ˆ์ œ

  • ๋ฌธ์ œ: P1์˜ S1 ์‹คํ–‰ ํ›„์—๋งŒ P2์˜ S2๊ฐ€ ์‹คํ–‰๋˜๋„๋ก ๋ณด์žฅ
1
2
3
4
5
6
7
8
9
10
11
12
// ์„ธ๋งˆํฌ์–ด ์ดˆ๊ธฐํ™”
semaphore sync = 0;  // ์ดˆ๊ธฐ๊ฐ’ 0์œผ๋กœ ์„ค์ •

// ํ”„๋กœ์„ธ์Šค Pโ‚
P1:
    Sโ‚;
    signal(sync);  // sync ๊ฐ’์„ 1๋กœ ์ฆ๊ฐ€

// ํ”„๋กœ์„ธ์Šค Pโ‚‚
P2:
    wait(sync);  // sync๊ฐ€ ์–‘์ˆ˜๊ฐ€ ๋  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐ
    Sโ‚‚;
  • semaphore sync๋Š” ์ดˆ๊ธฐ๊ฐ’์ด 0
  • P2๋Š” wait(sync)๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์ฆ‰์‹œ ๋ธ”๋ก๋จ(sync=0์ด๋ฏ€๋กœ)
  • P1์ด S1์„ ์ˆ˜ํ–‰ํ•˜๊ณ  signal(sync)๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด sync=1์ด ๋œ๋‹ค
  • ์ด์ œ P2๋Š” ๋ธ”๋ก ์ƒํƒœ์—์„œ ๋น ์ ธ๋‚˜์™€ S2๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค

Semaphore Implementation with no Busy waiting


์•ž์˜ ์„ธ๋งˆํฌ์–ด ๊ตฌํ˜„์—๋Š” buzy waiting ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด waiting queue๋ฅผ ์‚ฌ์šฉํ•ด ์„ธ๋งˆํฌ์–ด๋ฅผ ๊ตฌํ˜„!

  • semaphore ๊ตฌ์กฐ์ฒด:
1
2
3
4
typedef struct {
    int value;             // ์„ธ๋งˆํฌ์–ด ๊ฐ’
    struct process *list;  // ๋Œ€๊ธฐ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค ๋ฆฌ์ŠคํŠธ
} semaphore;

โœ…๊ตฌ์กฐ์ฒด์˜ ๋‘ ๊ฐ€์ง€ ์š”์†Œ:

  • value: ์„ธ๋งˆํฌ์–ด์˜ ์ •์ˆ˜ ๊ฐ’์œผ๋กœ, ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ž์›์˜ ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค
  • list: ์„ธ๋งˆํฌ์–ด๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ํ”„๋กœ์„ธ์Šค๋“ค์˜ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ(linked list)

์„ธ๋งˆํฌ์–ด ๊ตฌํ˜„์—๋Š” ๋‘ ๊ฐ€์ง€ ์—ฐ์‚ฐ์ด ์‚ฌ์šฉ๋œ๋‹ค

  1. block operation:
    • ์„ธ๋งˆํฌ์–ด๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ํ”„๋กœ์„ธ์Šค๋ฅผ ์ ์ ˆํ•œ waiting queue์— ๋„ฃ์Œ
    • ํ”„๋กœ์„ธ์Šค๋ฅผ ์‹คํ–‰ ์ƒํƒœ โ†’ ๋Œ€๊ธฐ ์ƒํƒœ ๋กœ ์ „ํ™˜
  2. wakeup operation
    • waiting queue์—์„œ ํ”„๋กœ์„ธ์Šค๋ฅผ ํ•˜๋‚˜ ์ œ๊ฑฐ
    • ์ œ๊ฑฐ๋œ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋Œ€๊ธฐ ์ƒํƒœ โ†’ ready ์ƒํƒœ ๋กœ ์ „ํ™˜
Implementation on single-core system
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
wait(semaphore *S) {
    disable interrupts;           // ์ธํ„ฐ๋ŸฝํŠธ ๋น„ํ™œ์„ฑํ™”
    S->value--;                   // ์„ธ๋งˆํฌ์–ด ๊ฐ’ ๊ฐ์†Œ
    if (S->value < 0) {           // ์ž์›์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ
        add this process to S->list;  // ๋Œ€๊ธฐ ํ์— ์ถ”๊ฐ€
        block();                  // ํ”„๋กœ์„ธ์Šค ๋ธ”๋ก
    }
    enable interrupts;            // ์ธํ„ฐ๋ŸฝํŠธ ํ™œ์„ฑํ™”
}

signal(semaphore *S) {
    disable interrupts;           // ์ธํ„ฐ๋ŸฝํŠธ ๋น„ํ™œ์„ฑํ™”
    S->value++;                   // ์„ธ๋งˆํฌ์–ด ๊ฐ’ ์ฆ๊ฐ€
    if (S->value <= 0) {          // ๋Œ€๊ธฐ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ
        remove a process P from S->list;  // ๋Œ€๊ธฐ ํ์—์„œ ํ”„๋กœ์„ธ์Šค ์ œ๊ฑฐ
        wakeup(P);                // ํ”„๋กœ์„ธ์Šค ๊นจ์šฐ๊ธฐ
    }
    enable interrupts;            // ์ธํ„ฐ๋ŸฝํŠธ ํ™œ์„ฑํ™”
}
  • single core์—์„œ๋Š” interrupt disable๋งŒ์œผ๋กœ ์›์ž์„ฑ์„ ๋ณด์žฅ โ†’ ๊ตฌํ˜„์ด ๊ฐ„๋‹จ
  • S->value:
    • S->value > 0: ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ž์›์˜ ์ˆ˜
    • S->value <= 0: ๋Œ€๊ธฐ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค์˜ ์ˆ˜๋Š” **S->value๊ฐœ**
Implementation on multicore system

multicore ์‹œ์Šคํ…œ์—์„œ๋Š” ๊ฐ ์ฝ”์–ด๊ฐ€ ๋…๋ฆฝ์ ์œผ๋กœ ์‹คํ–‰๋˜๊ณ , ํ•œ ์ฝ”์–ด์—์„œ ์ธํ„ฐ๋ŸฝํŠธ๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•ด๋„ ๋‹ค๋ฅธ ์ฝ”์–ด๋Š” ์‹คํ–‰ ๋œ๋‹ค
โ†’ ์ธํ„ฐ๋ŸฝํŠธ ๋น„ํ™œ์„ฑํ™”๋งŒ์œผ๋กœ๋Š” ์›์ž์„ฑ์„ ๋ณด์žฅ X

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
wait(semaphore *S) {
    while (test_and_set(&S->&mutex))  // mutex ํš๋“ ์‹œ๋„, ์„ธ๋งˆํฌ์–ด๋งˆ๋‹ค mutex๊ฐ€ ๋”ฐ๋กœ ์žˆ์–ด์•ผํ•จ
        ; /* spinlock */          // ํš๋“ํ•  ๋•Œ๊นŒ์ง€ ์Šคํ•€
    S->value--;                   // ์„ธ๋งˆํฌ์–ด ๊ฐ’ ๊ฐ์†Œ
    if (S->value < 0) {           // ์ž์›์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ
        add this process to S->list;  // ๋Œ€๊ธฐ ํ์— ์ถ”๊ฐ€
        S->mutex = 0;                // mutex ํ•ด์ œ
        block();                  // ํ”„๋กœ์„ธ์Šค ๋ธ”๋ก
    }
    else
        S->mutex = 0;                // mutex ํ•ด์ œ
    return;
}

signal(semaphore *S) {
    while (test_and_set(&S->&mutex))  // mutex ํš๋“ ์‹œ๋„
        ; /* spinlock */          // ํš๋“ํ•  ๋•Œ๊นŒ์ง€ ์Šคํ•€
    S->value++;                   // ์„ธ๋งˆํฌ์–ด ๊ฐ’ ์ฆ๊ฐ€
    if (S->value <= 0) {          // ๋Œ€๊ธฐ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ
        remove a process P from S->list;  // ๋Œ€๊ธฐ ํ์—์„œ ํ”„๋กœ์„ธ์Šค ์ œ๊ฑฐ
        S->mutex = 0;                // mutex ํ•ด์ œ
        wakeup(P);                // ํ”„๋กœ์„ธ์Šค ๊นจ์šฐ๊ธฐ
    }
    else
        S->mutex = 0;                // mutex ํ•ด์ œ
    return;
}
  • Spinlock ์‚ฌ์šฉ: Test-and-Set๊ณผ ๊ฐ™์€ ํ•˜๋“œ์›จ์–ด ์ง€์› ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•œ Spinlock์œผ๋กœ ์ž„๊ณ„์˜์—ญ์„ ๋ณดํ˜ธ
  • ๋‹ค์ค‘ ์ฝ”์–ด์—์„œ๋„ ์Šคํ•€๋ฝ์„ ํ†ตํ•ด ํ•œ ๋ฒˆ์— ํ•œ ํ”„๋กœ์„ธ์Šค๋งŒ ์„ธ๋งˆํฌ์–ด๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์„œ ์›์ž์„ฑ์„ ๋ณด์žฅ
  • mutex ๋ณ€์ˆ˜: ์„ธ๋งˆํฌ์–ด ์—ฐ์‚ฐ์˜ ์›์ž์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•œ ์ด์ง„ ๋ณ€์ˆ˜
  • ๋ธ”๋ก ์ „ mutex ํ—ค์ œ: ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋ธ”๋ก๋˜๊ธฐ ์ „์— ๋ฐ˜๋“œ์‹œ mutex๋ฅผ ํ•ด์ œํ•ด์•ผ ๋ฐ๋“œ๋ฝ ๋ฐฉ์ง€ ๊ฐ€๋Šฅ
This post is licensed under CC BY 4.0 by the author.