/* * 将当前进程设置为不可中断的睡眠状态 * 只有明确进程唤醒才可以 */ void sleep_on(struct task_struct **p) { struct task_struct *tmp; if (!p) return; if (current == &(init_task.task)) panic("task[0] trying to sleep"); tmp = *p; *p = current; current->state = TASK_UNINTERRUPTIBLE; schedule(); if (tmp) tmp->state=TASK_RUNNING; } void interruptible_sleep_on(struct task_struct **p) { struct task_struct *tmp; if (!p) return; if (current == &(init_task.task)) panic("task[0] trying to sleep"); tmp=*p; *p=current; repeat: current->state = TASK_INTERRUPTIBLE; schedule(); if (*p && *p != current) { (*p)->state = TASK_RUNNING; goto repeat; } /* Linux完全注释有如下 * 原来的代码中*p = NULL * 也会导致等待的进程可能没法唤醒,在嵌套的情况下 * 因此修改为*p = tmp * * 本人认为是错的,将*p = tmp不合适,因为在后面的代码中tmp已经被唤醒 * 设置为*p = NULL也不合适,因为当使用wake_up后设置*p为NULL,这个时候别的进程刚好掉用sleep_on函数 * 这样也会导致丢失, * 最好就是不管它就像sleep_on函数那样处理 */ //*p = tmp; if (tmp) tmp->state = TASK_RUNNING; } void wake_up(struct task_struct **p) { if (p && *p) { (*p)->state = TASK_RUNNING; /* * 原来的代码有*p = NULL,linux内核完全注释说是要删除掉 * 但是本人不认为要删掉 * 但是觉得应该保留 * 因为*p存放的是等待的第一个进程,第二个等待进程是存放在第一个堆栈中的 * 当第二个进程唤醒时,就会通过堆栈获取原来*p,并将其唤醒 * 以此类推唤醒所有进程 * 如果注释掉,可能导致多次唤醒,没有意义 */ *p = NULL; } }
代码如上修改,进行测试,运行不出错
标签:tmp,task,struct,up,current,state,wake,Linux0.11,sleep From: https://www.cnblogs.com/sudochen/p/16647372.html