linuxカーネル信号量


  sleepers:     ,                
count: (up , down )
wait(down , , spinlock )


57
fastcall
void __sched
__down
(struct semaphore
* sem
)

58

{

59

struct task_struct
*tsk
= current
;

60

DECLARE_WAITQUEUE
(wait
, tsk
);

61

unsigned long flags
;

62



63

tsk
->state
= TASK_UNINTERRUPTIBLE
;

64

spin_lock_irqsave
(&sem
->wait
.lock
, flags
);

65

add_wait_queue_exclusive_locked
(&sem
->wait
, &wait
);

66



67

sem
->sleepers
++;

68

for (;;) {

69

int sleepers
= sem
->sleepers
;

70



71

/*


72

* Add "everybody else" into it. They aren't


73

* playing, because we own the spinlock in


74

* the wait_queue_head.


75

*/


76

if (!atomic_add_negative
(sleepers
- 1, &sem
->count
)) {

77

sem
->sleepers
= 0;

78

break;

79

}

80

sem
->sleepers
= 1; /* us - see -1 above */


81

spin_unlock_irqrestore
(&sem
->wait
.lock
, flags
);

82



83

schedule
();

84



85

spin_lock_irqsave
(&sem
->wait
.lock
, flags
);

86

tsk
->state
= TASK_UNINTERRUPTIBLE
;

87

}

88

remove_wait_queue_locked
(&sem
->wait
, &wait
);

89

wake_up_locked
(&sem
->wait
);

90

spin_unlock_irqrestore
(&sem
->wait
.lock
, flags
);

91

tsk
->state
= TASK_RUNNING
;

92

}



(down0, up0), down(down1(up1), down2(up1)) case:

down1:
1. sem count 1, count -2
2. count , __down
3. TASK_UNINTERRUPTIBLE(line 63)
4. spin lock ( , down2 )(line 64)
5. (line65)
6. sleepers 1(line 67)
7. ,(line 68)
8. sleeper-1 count, count (line 76)
9. up0 call, count , sleepers 0, , , , (fter line88)
10. , sleepers 1, , , down2 , ,(line 80-83)
11.down2 , sleepers 1(=2), count = -2
12. down2 sleepers-1 count , count(-1) ,sleepers 1, , ,(line 80-83)
13. up0 call,count 0
14.down1 (up0 call__up wake_up ), spinlock, (line85)
15. sleepers-1=0 count, count , 0, , ,(line76-78)
16.
17. down1 (line88)
18. , down1 spinlock, , sleepers = 0, count = 0,(line89, line85)
19. spinlock(line90)
20. down1 TASK_RUNNING,(line91)
21. down2 spinlock,(line 85)
22. sleepers-1 = -1 count, count=-1(line 76)
23.count , sleepers =1, , (line80-83)
24. down1 , call up1 , count = 0, sleepers =1,
25. sleepers -1 = 0 count, count 0, ,down2 (line76)
26. , down2 ,(line88)
27. (line89)
28. , down2 TASK_RUNNING.(line90-91)

, down2


cpu

up
1. count
2. count , __up call wake_up


: , ,
FIFO 。

count
wait_list
wait_lock