LKD读书笔记(process Scheduling)

1.  Process Selection

      When CFS is deciding what process to run next , it picks the process with the smallest vruntime. This is the core of CFS's scheduling algotithm: Pick the task with the smallest vruntime.

      CFS uses a red-black tree to manage the list of runnable processes and efficiently find the process with the smallest vruntiome.


2. Pick the Next Task

static struct sched_entyty *_pick_next_entity(struct cfs_rq *cfs_rq)
{
    struct rb_node *left = cfs_rq->rb_leftmost;
    if (!left)
        return NULL;
    return rb_entry(left, struct sched_entity, run_node);
}



3. adding processes to the tree

   这个发生在一个进程变成runnable状态或者第一次通过fork()创建

cfs_rq:  CFS-related fields in a runqueue

 310struct cfs_rq {
 311        struct load_weight load;
 312        unsigned long nr_running;
 313
 314        u64 exec_clock;
 315        u64 min_vruntime;
 316
 317        struct rb_root tasks_timeline;
 318        struct rb_node *rb_leftmost;
 319
 320        struct list_head tasks;
 321        struct list_head *balance_iterator;
 322
 323        /*
 324         * 'curr' points to currently running entity on this cfs_rq.
 325         * It is set to NULL otherwise (i.e when none are currently running).
 326         */
 327        struct sched_entity *curr, *next, *last;
 328
 329        unsigned int nr_spread_over;
 330
 331#ifdef CONFIG_FAIR_GROUP_SCHED
 332        struct rq *rq;  /* cpu runqueue to which this cfs_rq is attached */
 333
 334        /*
 335         * leaf cfs_rqs are those that hold tasks (lowest schedulable entity in
 336         * a hierarchy). Non-leaf lrqs hold other higher schedulable entities
 337         * (like users, containers etc.)
 338         *
 339         * leaf_cfs_rq_list ties together list of leaf cfs_rq's in a cpu. This
 340         * list is used during load balance.
 341         */
 342        int on_list;
 343        struct list_head leaf_cfs_rq_list;
 344        struct task_group *tg;  /* group that "owns" this runqueue */
 345
 346#ifdef CONFIG_SMP
 347        /*
 348         * the part of load.weight contributed by tasks
 349         */
 350        unsigned long task_weight;
 351
 352        /*
 353         *   h_load = weight * f(tg)
 354         *
 355         * Where f(tg) is the recursive weight fraction assigned to
 356         * this group.
 357         */
 358        unsigned long h_load;
 359
 360        /*
 361         * Maintaining per-cpu shares distribution for group scheduling
 362         *
 363         * load_stamp is the last time we updated the load average
 364         * load_last is the last time we updated the load average and saw load
 365         * load_unacc_exec_time is currently unaccounted execution time
 366         */
 367        u64 load_avg;
 368        u64 load_period;
 369        u64 load_stamp, load_last, load_unacc_exec_time;
 370
 371        unsigned long load_contribution;
 372#endif
 373#endif
 374};


 966static void
 967enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
 968{
 969        /*
 970         * Update the normalized vruntime before updating min_vruntime
 971         * through callig update_curr().
 972         */
 973        if (!(flags & ENQUEUE_WAKEUP) || (flags & ENQUEUE_WAKING))
 974                se->vruntime += cfs_rq->min_vruntime;
 975
 976        /*
 977         * Update run-time statistics of the 'current'.
 978         */
 979        update_curr(cfs_rq);
 980        update_cfs_load(cfs_rq, 0);
 981        update_cfs_shares(cfs_rq, se->load.weight);
 982        account_entity_enqueue(cfs_rq, se);
 983
 984        if (flags & ENQUEUE_WAKEUP) {
 985                place_entity(cfs_rq, se, 0);
 986                enqueue_sleeper(cfs_rq, se);
 987        }
 988
 989        update_stats_enqueue(cfs_rq, se);
 990        check_spread(cfs_rq, se);
 991        if (se != cfs_rq->curr)
 992                __enqueue_entity(cfs_rq, se);
 993        se->on_rq = 1;
 994
 995        if (cfs_rq->nr_running == 1)
 996                list_add_leaf_cfs_rq(cfs_rq);
 997}
 998

 370/*
 371 * Enqueue an entity into the rb-tree:
 372 */
 373static void __enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
 374{
 375        struct rb_node **link = &cfs_rq->tasks_timeline.rb_node;
 376        struct rb_node *parent = NULL;
 377        struct sched_entity *entry;
 378        s64 key = entity_key(cfs_rq, se);
 379        int leftmost = 1;
 380
 381        /*
 382         * Find the right place in the rbtree:
 383         */
 384        while (*link) {
 385                parent = *link;
 386                entry = rb_entry(parent, struct sched_entity, run_node);
 387                /*
 388                 * We dont care about collisions. Nodes with
 389                 * the same key stay together.
 390                 */
 391                if (key < entity_key(cfs_rq, entry)) {
 392                        link = &parent->rb_left;
 393                } else {
 394                        link = &parent->rb_right;
 395                        leftmost = 0;
 396                }
 397        }
 398
 399        /*
 400         * Maintain a cache of leftmost tree entries (it is frequently
 401         * used):
 402         */
 403        if (leftmost)
 404                cfs_rq->rb_leftmost = &se->run_node;
 405
 406        rb_link_node(&se->run_node, parent, link);
 407        rb_insert_color(&se->run_node, &cfs_rq->tasks_timeline);
 408}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值