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
73
74
75
76
if (!atomic_add_negative
(sleepers
- 1, &sem
->count
)) {
77
sem
->sleepers
= 0;
78
break;
79
}
80
sem
->sleepers
= 1;
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