В настоящее время я читаю «Развитие ядра Linux» Роберта Лава, и у меня появилось несколько вопросов о CFS. Мой вопрос заключается в том, как calc_delta_mine вычисляет:Объяснение функции calc_delta_mine
delta_exec_weighted = (delta_exec * вес) вес
/lw-> Я предполагаю, что это делается в два этапа:
расчета (delta_exec * 1024):
if (likely(weight > (1UL << SCHED_LOAD_RESOLUTION))) tmp = (u64)delta_exec * scale_load_down(weight); else tmp = (u64)delta_exec;
вычислить/lw-> вес (или * 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);
СРР (Сдвиг вправо и раунд) макрос определяется с помощью:
#define SRR(x, y) (((x) + (1UL << ((y) - 1))) >> (y))
И другие макрокоманды определены:
#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 < < 32))?
спасибо. поэтому, если я снова посмотрю на макрос SRR, я понимаю, что '(1UL << ((y) - 1))' является '2^(y-1)' и '((x) + (1UL << ((y) - 1))) '' 'x + 2^(y-1)'. Итак, последняя часть принимает результат и сдвигает его '>> (y)', чтобы вернуть его с 32.32 в исходное представление? – arkadish
'>> (y)' является разделом * на 2^y *. 'SRR' работает только с целыми числами; ему все равно, если результаты 32.32 или нет.'calc_delta_mine' использует его для выполнения вычислений на 32.32 числах. – nneonneo
Кажется, tmp находится в целочисленной форме: 'tmp = (u64) delta_exec * scale_load_down (weight);' когда 'lw-> inv_weight = WMULT_CONST/w' находится в форме 32.32. Я думаю, переместив там умножение на '>> 32', я снова получаю его в целочисленную форму, это более разумно, потому что vruntime является целым числом и не должен быть представлен как 32.32. – arkadish