免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1984 | 回复: 7
打印 上一主题 下一主题

请问源码__down实现中的一个问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-11-24 17:09 |只看该作者 |倒序浏览
问题比较小白,还请大家告知,谢谢了先。
在进程执行__down的时候,如果在"tsk->state = TASK_UNINTERRUPTIBLE"这条语句执行完毕后,刚好进程的时间片用完了,进程让出了CPU,而状态又成为了TASK_UNINTERRUPTIBLE,那__down剩下的部分什么时候得以执行?
fastcall void __sched __down(struct semaphore * sem)
{
    struct task_struct *tsk = current;
    DECLARE_WAITQUEUE(wait, tsk);
    unsigned long flags;

    tsk->state = TASK_UNINTERRUPTIBLE;
    spin_lock_irqsave(&sem->wait.lock, flags);
    add_wait_queue_exclusive_locked(&sem->wait, &wait);

    sem->sleepers++;
    for (;;) {
        int sleepers = sem->sleepers;

        /*
         * Add "everybody else" into it. They aren't
         * playing, because we own the spinlock in
         * the wait_queue_head.
         */

        if (!atomic_add_negative(sleepers - 1, &sem->count)) {
            sem->sleepers = 0;
            break;
        }
        sem->sleepers = 1;    /* us - see -1 above */
        spin_unlock_irqrestore(&sem->wait.lock, flags);

        schedule();

        spin_lock_irqsave(&sem->wait.lock, flags);
        tsk->state = TASK_UNINTERRUPTIBLE;
    }
    remove_wait_queue_locked(&sem->wait, &wait);
    wake_up_locked(&sem->wait);
    spin_unlock_irqrestore(&sem->wait.lock, flags);
    tsk->state = TASK_RUNNING;
}

论坛徽章:
0
2 [报告]
发表于 2008-11-25 12:37 |只看该作者

回复 #1 fishswimming 的帖子

没有问题的,总会有另一个进程会执行up(sem),这个时候下面部分就可以执行了,只是执行过程中发现睡眠条件不再满足,通过break直接退出而已

论坛徽章:
0
3 [报告]
发表于 2008-11-25 13:54 |只看该作者
不会在那句后面被调度的,因为那时候是关中断的

论坛徽章:
0
4 [报告]
发表于 2008-11-25 16:39 |只看该作者
原帖由 bluesky_jxc 于 2008-11-25 12:37 发表
没有问题的,总会有另一个进程会执行up(sem),这个时候下面部分就可以执行了,只是执行过程中发现睡眠条件不再满足,通过break直接退出而已


但是进程还没有执行“add_wait_queue_exclusive_locked(&sem->wait, &wait)”时间片就用完了,故并不在待唤醒队列中啊

论坛徽章:
0
5 [报告]
发表于 2008-11-25 16:41 |只看该作者
原帖由 pipipen 于 2008-11-25 13:54 发表
不会在那句后面被调度的,因为那时候是关中断的

请问是在何处关闭中断的?没有找到

论坛徽章:
0
6 [报告]
发表于 2008-11-25 17:06 |只看该作者
呵呵,查了很长时间才搞清楚 v2.6.0

如果在tsk->state = TASK_UNINTERRUPTIBLE;时间片被用完,而此时恰巧发生时钟中断

do_timer->update_process_times->scheduler_tick->set_tsk_need_resched
static inline void set_tsk_need_resched(struct task_struct *tsk)
{
        set_tsk_thread_flag(tsk,TIF_NEED_RESCHED);
}

设置need resched标志

中断返回
ret_from_intr:
        GET_THREAD_INFO(%ebp)
        movl EFLAGS(%esp), %eax                # mix EFLAGS and CS
        movb CS(%esp), %al
        testl $(VM_MASK | 3), %eax
        jz resume_kernel                # returning to kernel or vm86-space

#ifdef CONFIG_PREEMPT
ENTRY(resume_kernel)
        cmpl $0,TI_PRE_COUNT(%ebp)        # non-zero preempt_count ?
        jnz restore_all
need_resched:
        movl TI_FLAGS(%ebp), %ecx        # need_resched set ?
        testb $_TIF_NEED_RESCHED, %cl
        jz restore_all
        testl $IF_MASK,EFLAGS(%esp)     # interrupts off (exception path) ?
        jz restore_all
        movl $PREEMPT_ACTIVE,TI_PRE_COUNT(%ebp)
        sti
        call schedule
        movl $0,TI_PRE_COUNT(%ebp)
        cli
        jmp need_resched
#endif

注意这里
        movl $PREEMPT_ACTIVE,TI_PRE_COUNT(%ebp)
        sti
        call schedule
        movl $0,TI_PRE_COUNT(%ebp)
        cli
先置        ti->preempt_count = PREEMPT_ACTIVE;然后调度schedule

在schedule中
        if (unlikely(preempt_count() & PREEMPT_ACTIVE))
                goto pick_next_task;
        switch (prev->state) {
        case TASK_INTERRUPTIBLE:
                if (unlikely(signal_pending(prev))) {
                        prev->state = TASK_RUNNING;
                        break;
                }
        default:
                deactivate_task(prev, rq);
                prev->nvcsw++;
                break;
        case TASK_RUNNING:
                prev->nivcsw++;
        }
pick_next_task:

直接跳到pick_next_task,而不将该进程脱离run queue,则下次还会被调度到

论坛徽章:
0
7 [报告]
发表于 2008-11-26 00:16 |只看该作者
原帖由 qtdszws 于 2008-11-25 17:06 发表
呵呵,查了很长时间才搞清楚 v2.6.0

如果在tsk->state = TASK_UNINTERRUPTIBLE;时间片被用完,而此时恰巧发生时钟中断

do_timer->update_process_times->scheduler_tick->set_tsk_need_resched
static i ...

明白了,只要schedule()是因为时间片用完被调用,不论进程的状态如何,都不会被移出run queue。
多谢多谢,辛苦辛苦

[ 本帖最后由 fishswimming 于 2008-11-26 00:23 编辑 ]

论坛徽章:
0
8 [报告]
发表于 2008-11-26 08:43 |只看该作者
呵呵,不客气,对2.6的内核不熟悉,看过LINUX内核设计与实现(第2版)
忘差不多了,你的结论很好
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP