Linux0.11 sleep_on函数分析

 

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/*
 * 将当前进程设置为不可中断的睡眠状态
 * 只能通过wake_up进行唤醒
 *
 */
void sleep_on(struct task_struct **p)
{
    struct task_struct *tmp;
 
    if (!p)
        return;
    /*
     * task[0]不允许睡眠
     */
    if (current == &(init_task.task))
        panic("task[0] trying to sleep");
    /*
     *
     * 第一次调用时,*p为空,表示当前进程是第一个睡眠进程
     * 第二次调用时,*p表示上次睡眠的进程任务指针,将上次睡眠的进程任务指针
     *    存放在当前进程的栈中,并使用当前进程任务指针替换*p,此时
     *    当前进程任务指针为睡眠进程的头部
     * 当唤醒时,将头部睡眠进程的状态设置为运行状态,然后判断tmp进行递归唤醒
     *
     */
    tmp = *p;
    *p = current;
    current->state = TASK_UNINTERRUPTIBLE;
    schedule();
    /*
     * 进程唤醒后走到这,然后判断栈中的tmp进程指针如果有效则递归唤醒
     *
     */
    if (tmp)
        tmp->state = TASK_RUNNING;
}
 
/*
 * 将当前进程设置为可中断的睡眠状态
 * 通过wake_up或者信号进行唤醒
 *
 */
void interruptible_sleep_on(struct task_struct **p)
{
    struct task_struct *tmp;
 
    if (!p)
        return;
    /*
     * task[0]不允许睡眠
     */
    if (current == &(init_task.task))
        panic("task[0] trying to sleep");
    /*
     * 和sleep_on函数的说明一样,但是唤醒后的处理不一样
     */
    tmp = *p;
    *p = current;
 
    /* *p表示的永远是最后一个睡眠的进程指针,也就是睡眠进程头部
     *
     */
repeat:   
    current->state = TASK_INTERRUPTIBLE;
    schedule();
    /*
     * 当某个进程被唤醒时,如果这个进程不是头部,则将头部进程唤醒,
     * 自己继续进入睡眠状态,头部进程唤醒后递归唤醒所有进程
     * 在这个增加了 *p = NULL
     *
     *
     */
    if (*p && *p != current) {
        (*p)->state = TASK_RUNNING;
        *p = NULL;
        goto repeat;
    }
    /* Linux完全注释有如下
     * 原来的代码中*p = NULL
     * 也会导致等待的进程可能没法唤醒,在嵌套的情况下
     * 因此修改为*p = tmp
     *
     * 我个人认为将*p = tmp不合适,*p已经是头部,
     * 头部进行唤醒后会递归进行tmp指向的进程的唤醒
     * 如果将*p = tmp进行修改
     * 因为在后面的代码中tmp已经被唤醒
     * 当tmp被唤醒会进行递归回溯唤醒所有的进程
     * 设置为*p = NULL也不合适,因为当使用wake_up唤醒后设置*p为NULL
     * 如果这个时候别的进程刚好掉用sleep_on函数, *p是有内容的
     * 这样也会导致丢失,
     * 最好的处理方式就是在如上代码的(*p)->state = TASK_RUNNING
     * 的下面增加*p = NULL和wake_up的处理方式一样
     */
     
    if (tmp)
        tmp->state = TASK_RUNNING;
}

 

posted on   sudochen  阅读(194)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律

导航

< 2025年3月 >
23 24 25 26 27 28 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 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示