进程调度中函数cpupri_find解析

从cpu优先级中cp中找到task p可以使用的优先级最低的那些cpu报保存到lowest_mask中

int cpupri_find(struct cpupri *cp, struct task_struct *p,
        struct cpumask *lowest_mask)
{
    int idx = 0;
    int task_pri = convert_prio(p->prio);//将p的优先级进行转换,idle为0,普通进程为1,实时进程进行转换
    bool drop_nopreempts = task_pri <= MAX_RT_PRIO;//判断是否可以放弃不能抢占的

    BUG_ON(task_pri >= CPUPRI_NR_PRIORITIES);//检查task_pri是否异常

retry:
    for (idx = 0; idx < task_pri; idx++) {
        struct cpupri_vec *vec  = &cp->pri_to_cpu[idx];//从idle cpu开始进行
        int skip = 0;

        if (!atomic_read(&(vec)->count))//判断cpu个数
            skip = 1;
        /*
         * When looking at the vector, we need to read the counter,
         * do a memory barrier, then read the mask.
         *
         * Note: This is still all racey, but we can deal with it.
         *  Ideally, we only want to look at masks that are set.
         *
         *  If a mask is not set, then the only thing wrong is that we
         *  did a little more work than necessary.
         *
         *  If we read a zero count but the mask is set, because of the
         *  memory barriers, that can only happen when the highest prio
         *  task for a run queue has left the run queue, in which case,
         *  it will be followed by a pull. If the task we are processing
         *  fails to find a proper place to go, that pull request will
         *  pull this task if the run queue is running at a lower
         *  priority.
         */
        smp_rmb();

        /* Need to do the rmb for every iteration */
        if (skip)
            continue;

        if (cpumask_any_and(tsk_cpus_allowed(p), vec->mask) >= nr_cpu_ids)//判断p允许运行的cpu是否存在vec->mask中
            continue;

        if (lowest_mask) {
            cpumask_and(lowest_mask, tsk_cpus_allowed(p), vec->mask);//将p允许运行的cpu并且在vec->mask中的给到lowest_mask
            cpumask_andnot(lowest_mask, lowest_mask,
                       cpu_isolated_mask);//将lowest_mask中隔离的cpu删除
            if (drop_nopreempts)
                drop_nopreempt_cpus(lowest_mask);//将lowest_mask中不能被抢占的cpu删除
            /*
             * We have to ensure that we have at least one bit
             * still set in the array, since the map could have
             * been concurrently emptied between the first and
             * second reads of vec->mask.  If we hit this
             * condition, simply act as though we never hit this
             * priority level and continue on.
             */
            if (cpumask_any(lowest_mask) >= nr_cpu_ids)//lowest_mask如果不存在cpu将进行循环
                continue;
        }

        return 1;
    }
    /*
     * If we can't find any non-preemptible cpu's, retry so we can
     * find the lowest priority target and avoid priority inversion.
     */
    if (drop_nopreempts) {
        drop_nopreempts = false;
        goto retry;
    }
    return 0;
}
 

你可能感兴趣的:(进程管理,linux)