免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2933 | 回复: 7

cfs问题 [复制链接]

论坛徽章:
16
2015亚冠之吉达阿赫利
日期:2015-08-17 11:21:462015年迎新春徽章
日期:2015-03-04 09:58:11酉鸡
日期:2014-12-07 09:06:19水瓶座
日期:2014-11-04 14:23:29天秤座
日期:2014-03-02 08:57:52双鱼座
日期:2014-02-22 13:07:56午马
日期:2014-02-14 11:08:18双鱼座
日期:2014-02-13 11:09:37卯兔
日期:2014-02-06 15:10:34子鼠
日期:2014-01-20 14:48:19戌狗
日期:2013-12-19 09:37:46射手座
日期:2013-12-19 09:33:47
发表于 2011-12-08 15:09 |显示全部楼层
30可用积分
本帖最后由 embeddedlwp 于 2011-12-08 22:25 编辑

在scheduler函数中会调用put_prev_task_fair函数和pick_next_task_fair函数,其中put_prev_task_fair函数会调用到 put_prev_entity函数:
  1. 833static void put_prev_entity(struct cfs_rq *cfs_rq, struct sched_entity *prev)
  2. 834{
  3. 835        /*
  4. 836         * If still on the runqueue then deactivate_task()
  5. 837         * was not called and update_curr() has to be done:
  6. 838         */
  7. 839        if (prev->on_rq)
  8. 840                update_curr(cfs_rq);
  9. 841
  10. 842        check_spread(cfs_rq, prev);
  11. 843        if (prev->on_rq) {
  12. 844                update_stats_wait_start(cfs_rq, prev);
  13. 845                /* Put 'current' back into the tree. */
  14. 846                __enqueue_entity(cfs_rq, prev);
  15. 847        }
  16. 848        cfs_rq->curr = NULL;
  17. 849}
复制代码
pick_next_task_fair函数会调用到set_next_entity函数:
  1. 788set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
  2. 789{
  3. 790        /* 'current' is not kept within the tree. */
  4. 791        if (se->on_rq) {
  5. 792                /*
  6. 793                 * Any task has to be enqueued before it get to execute on
  7. 794                 * a CPU. So account for the time it spent waiting on the
  8. 795                 * runqueue.
  9. 796                 */
  10. 797                update_stats_wait_end(cfs_rq, se);
  11. 798                __dequeue_entity(cfs_rq, se);
  12. 799        }
  13. 800
  14.            ...............
  15. 815}
复制代码
有两个地方不明白:
1)之前的调度实体问什么还有加入cfs_rq,而下一个要运行的进程却要移除cfs_rq?
2)on_rq有什么用,prev如果是on_rq,怎么还加入cfs_rq?

求指点!

最佳答案

查看完整内容

按我的理解,这个地方有两个概念:1、task在不在runqueue中(由p->se.on_rq表示);2、task在不在rb树中;"task在runqueue中"跟"task是TASK_RUNNING状态"是对应的。也就是说,进入TASK_RUNNING状态的进程会被加入runqueue,然后将on_rq置1;离开TASK_RUNNING状态的进程会被从runqueue中移除,然后将on_rq置0。当然,里面存在中间状态,比如TASK_RUNNING状态的进程可能暂时尚未加入runqueue。而"task在runqueue中"且"task不在rb树中 ...

论坛徽章:
0
发表于 2011-12-08 15:09 |显示全部楼层
按我的理解,这个地方有两个概念:
1、task在不在runqueue中(由p->se.on_rq表示);
2、task在不在rb树中;

"task在runqueue中"跟"task是TASK_RUNNING状态"是对应的。也就是说,进入TASK_RUNNING状态的进程会被加入runqueue,然后将on_rq置1;离开TASK_RUNNING状态的进程会被从runqueue中移除,然后将on_rq置0。当然,里面存在中间状态,比如TASK_RUNNING状态的进程可能暂时尚未加入runqueue。

而"task在runqueue中"且"task不在rb树中",则意味着task是正在CPU上运行的那个进程。所以对于正在运行的task,它会被从rb树中移除。
所以,prev是即将从CPU上释放下来的进程,它应该放回rb树;而next是即将放到CPU上面去运行的进程,它应该从rb树中移除。
然后,在这个时刻,prev可能已经不是TASK_RUNNING状态了,它可能是因为进入睡眠或者退出了,才需要从CPU上释放下来的。那么这种情况下prev会先被从runqueue中移除,其on_rq已经置0。所以prev从CPU上释放下来的时候,如果on_rq为0,就不需要再加入rb树了。

论坛徽章:
0
发表于 2011-12-08 15:55 |显示全部楼层
这块不太熟啊,帮顶吧~

论坛徽章:
0
发表于 2011-12-08 17:39 |显示全部楼层
本帖最后由 wangjianchangdx 于 2011-12-08 17:40 编辑

>1)之前的调度实体问什么还有加入cfs_rq,而下一个要运行的进程却要移除cfs_rq?
个人以为,是要通过enqueue和dequeue完成对entity rbtree的维护,没看到其他调整rbtree的途径;

>2)on_rq有什么用,prev如果是on_rq,怎么还加入cfs_rq?
这个要看on_rq是在哪里改变的:enqueue_task & dequeue_task;
你看的是sched_fair.c里面的代码,所以是cfs_rq;
这里的on_rq指的是runqueue,而非cfs_rq,同一个runqueue里面的task可以有多种调度方式;
这里如果不on_rq也就是task被从runqueue中移除了,还有必要加入到属于runqueue的cfs_rq里面吗?
  1. /*
  2. * activate_task - move a task to the runqueue.
  3. */
  4. static void activate_task(struct rq *rq, struct task_struct *p, int flags)
  5. {
  6.         if (task_contributes_to_load(p))
  7.                 rq->nr_uninterruptible--;

  8.         enqueue_task(rq, p, flags);
  9.         inc_nr_running(rq);
  10. }
复制代码
  1. static void enqueue_task(struct rq *rq, struct task_struct *p, int flags)
  2. {
  3.         update_rq_clock(rq);
  4.         sched_info_queued(p);
  5.         p->sched_class->enqueue_task(rq, p, flags);
  6.         p->se.on_rq = 1;
  7. }
复制代码

论坛徽章:
0
发表于 2011-12-08 17:51 |显示全部楼层
本帖最后由 wangjianchangdx 于 2011-12-08 18:24 编辑
static void
dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
{
        /*
         * Update run-time statistics of the 'current'.
         */
        update_curr(cfs_rq);

        update_stats_dequeue(cfs_rq, se);
        if (flags & DEQUEUE_SLEEP) {
#ifdef CONFIG_SCHEDSTATS
                if (entity_is_task(se)) {
                        struct task_struct *tsk = task_of(se);

                        if (tsk->state & TASK_INTERRUPTIBLE)
                                se->statistics.sleep_start = rq_of(cfs_rq)->clock;
                        if (tsk->state & TASK_UNINTERRUPTIBLE)
                                se->statistics.block_start = rq_of(cfs_rq)->clock;
                }
#endif
        }

        clear_buddies(cfs_rq, se);

        if (se != cfs_rq->curr)
                __dequeue_entity(cfs_rq, se);

在entity为当前进程的情况下,也要将他从rq中删除,即on_rq置零,所以下一次put prev entity的时候,需要检查on_rq了。

论坛徽章:
16
2015亚冠之吉达阿赫利
日期:2015-08-17 11:21:462015年迎新春徽章
日期:2015-03-04 09:58:11酉鸡
日期:2014-12-07 09:06:19水瓶座
日期:2014-11-04 14:23:29天秤座
日期:2014-03-02 08:57:52双鱼座
日期:2014-02-22 13:07:56午马
日期:2014-02-14 11:08:18双鱼座
日期:2014-02-13 11:09:37卯兔
日期:2014-02-06 15:10:34子鼠
日期:2014-01-20 14:48:19戌狗
日期:2013-12-19 09:37:46射手座
日期:2013-12-19 09:33:47
发表于 2011-12-08 19:18 |显示全部楼层
感谢各位!

论坛徽章:
0
发表于 2012-08-13 10:57 |显示全部楼层
为什么要把当前运行的进程从红黑树中取出来??

论坛徽章:
0
发表于 2012-08-14 10:11 |显示全部楼层
scopengl 发表于 2012-08-13 10:57
为什么要把当前运行的进程从红黑树中取出来??


我觉得是否把current从红黑树拿出来并不是原则性问题。不过如果不拿出来的话,因为current每个tick都会更新vruntime,会导致每个tick都需要更新current在红黑树中的位置,这个有点恶心了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP