内核版本:
linux-4.4.249
函数签名:
__update_inv_weight(struct load_weight *lw)
文件位置:
./kernel/sched/fair.c
功能&原理解析:
(1)该函数的作用是,如果lw->inv_weight不为0,不作任何修改函数直接返回;否则,更新lw->inv_weight的值为lw->inv_weight = max(1, min(WMULT_CONST * 1024 / lw->weight, WMULT_CONST))
(2) 如果更新lw->inv_weight都是通过调用该函数实现的,说明lw->inv_weight仅有一次被更新为非0的机会,更新的值为 max(1, min(WMULT_CONST * 1024 / lw->weight, WMULT_CONST)), 且lw->inv_weight的值仅仅与调用该函数时的lw->weight的值有关(因为不确定lw->weight是否随着时间会发生变化,因而这里说当时调用该函数时lw->weight的值更准确些)
前置依赖知识点:
(1) #define WMULT_CONST (~0U)
文件位置:同一个文件内(./kernel/sched/fair.c)
(2) likely解读:参考 https://cosysn.github.io/2017/01/14/introduction-to-linux-kernel-2-likey-and-unlieky/
具体实现解析:
static void __update_inv_weight(struct load_weight *lw)
{
unsigned long w;
if (likely(lw->inv_weight)) //如果lw->inv_weight非0,则直接返回了。如果更新lw->inv_weight都是通过调用该函数实现的,说明lw->inv_weight仅有一次被更新为非0的机会,更新的值为 max(1, min(WMULT_CONST * 1024 / lw->weight, WMULT_CONST)), 且lw->inv_weight的值仅仅与调用该函数时的lw->weight的值有关(因为不确定lw->weight是否随着时间会发生变化,因而这里说当时调用该函数时lw->weight的值)
return;
w = scale_load_down(lw->weight); // 当前版本等价于:w = lw->weight/1024;
if (BITS_PER_LONG > 32 && unlikely(w >= WMULT_CONST))
lw->inv_weight = 1; // w >= WMULT_CONST, 即WMULT_CONST / w 小于等于1,其等价于“WMULT_CONST * 1024/lw->weight 小于等于 1”,那么其表达的意思就是lw->inv_weight = max(1, WMULT_CONST * 1024/lw->weight), 即(1)当lw->weight的值大于WMULT_CONST * 1024(即2^42次方)时,lw->inv_weight = 1;
else if (unlikely(!w))
lw->inv_weight = WMULT_CONST; // (2)当w=0时,意味着当lw->weight=0,则lw->weight不能为分母,因而相当于lw->inv_weight=min(WMULT_CONST * 1024/lw->weight, WMULT_CONST)
else
lw->inv_weight = WMULT_CONST / w; // 其他情况,(3)即当 0 < lw->weight < 2 ^ 42时,则lw->inv_weight = WMULT_CONST * 1024 / lw->weight;
//综合上述 这三条if...else...,其表达的意思就是lw->inv_weight的值的计算方式为lw->inv_weight = max(1, min(WMULT_CONST * 1024 / lw->weight, WMULT_CONST
}
(1) 1, 当且仅当lw->weight > 2^42
即: lw->inv_weight = (2) WMULT_CONST, 当且仅当lw->weight = 0
(3) WMULT_CONST / ( lw->weight / 1024), 其他,即当 0 < lw->weight < 2^42
由此也可以看出lw->inv_weight的最大值就是WMULT_CONST, 最小值为1, 也可以表述为在2^32取值内