我目前正在阅读罗伯特·洛夫的“Linux内核开发”,我收到了一些关于CFS的问题。 我的问题是calc_delta_mine如何计算:
delta_exec_weighted =(delta_exec * weight)/ lw-> weight
我想这是通过两个步骤完成的:
计算(delta_exec * 1024):
if (likely(weight > (1UL << SCHED_LOAD_RESOLUTION)))
tmp = (u64)delta_exec * scale_load_down(weight);
else
tmp = (u64)delta_exec;
计算/ lw-&gt;重量(或* lw-> inv_weight):
if (!lw->inv_weight) {
unsigned long w = scale_load_down(lw->weight);
if (BITS_PER_LONG > 32 && unlikely(w >= WMULT_CONST))
lw->inv_weight = 1;
else if (unlikely(!w))
lw->inv_weight = WMULT_CONST;
else
lw->inv_weight = WMULT_CONST / w;
}
/*
* Check whether we'd overflow the 64-bit multiplication:
*/
if (unlikely(tmp > WMULT_CONST))
tmp = SRR(SRR(tmp, WMULT_SHIFT/2) * lw->inv_weight,
WMULT_SHIFT/2);
else
tmp = SRR(tmp * lw->inv_weight, WMULT_SHIFT);
return (unsigned long)min(tmp, (u64)(unsigned long)LONG_MAX);
SRR(右移和右移)宏通过以下方式定义:
#define SRR(x, y) (((x) + (1UL << ((y) - 1))) >> (y))
其他MACROS定义为:
#if BITS_PER_LONG == 32
# define WMULT_CONST (~0UL)
#else
# define WMULT_CONST (1UL << 32)
#endif
#define WMULT_SHIFT 32
有人可以解释SRR的确切工作原理以及如何检查64位乘法溢出? 请解释此函数中MACROS的定义((~0UL),(1UL&lt;&lt; 32))?
答案 0 :(得分:4)
您发布的代码基本上是使用32.32定点运算进行计算,其中单个64位数量保持数字的整数部分为高32位,数字的小数部分为低32位(例如,在该系统中,1.5是0x0000000180000000)。因此,WMULT_CONST
是1.0的近似值(使用适合平台效率考虑的long
值),因此将WMULT_CONST
除以w
计算{{1} }作为32.32值。
请注意,将两个32.32值一起乘以整数会产生2 32 倍的结果;因此,1/w
(= 32)是将两个32.32值相乘的结果归一化为32.32所需的右移值。
WMULT_SHIFT
至于/*
* Increase resolution of nice-level calculations for 64-bit architectures.
* The extra resolution improves shares distribution and load balancing of
* low-weight task groups (eg. nice +19 on an autogroup), deeper taskgroup
* hierarchies, especially on larger systems. This is not a user-visible change
* and does not change the user-interface for setting shares/weights.
*
* We increase resolution only if we have enough bits to allow this increased
* resolution (i.e. BITS_PER_LONG > 32). The costs for increasing resolution
* when BITS_PER_LONG <= 32 are pretty high and the returns do not justify the
* increased costs.
*/
,在数学上,它会计算SRR
的舍入结果。
要对分部x / 2y
的结果进行舍入,您可以计算x/q
最低分数x + q/2
;这就是SRR通过计算q
下限除以x + 2y-1
来做的事情。