Меня смущает формулировка на странице руководства arch_prctl(2)
. В частности, в нем говорится:
Контекстные коммутаторы для 64-разрядных базовых сегментов довольно дороги. Это может быть более быстрой альтернативой для установки 32-разрядной базы с использованием селектора сегментов путем установки LDT с помощью modify_ldt (2) или использования set_thread_area (2) системный вызов в ядре 2.5 или новее. arch_prctl() требуется только тогда, когда вы хотите установить базы размером более 4 ГБ. Память в первом 2 ГБ адресного пространства может быть выделено с помощью mmap (2) с помощью Флаг MAP_32BIT.
Означает ли это, что переключатели контекста для процесса, использующего этот системный вызов, получат штраф за производительность или точные последствия?
После просмотра источника ядра Linux выяснится, что для адресов, которые являются < 4 GiB, используют LDT, a > 4 адреса GiB используют регистр, специфичный для модели.
Из do_arch_prctl
:
case ARCH_SET_FS:
/* handle small bases via the GDT because that faster to
switch. */
if (addr <= 0xffffffff) {
set_32bit_tls(task, FS_TLS, addr);
if (doit) {
load_TLS(&task->thread, cpu);
loadsegment(fs, FS_TLS_SEL);
}
task->thread.fsindex = FS_TLS_SEL;
task->thread.fs = 0;
} else {
task->thread.fsindex = 0;
task->thread.fs = addr;
if (doit) {
/* set the selector to 0 to not confuse
__switch_to */
loadsegment(fs, 0);
ret = wrmsrl_safe(MSR_FS_BASE, addr);
}
}
put_cpu();
break;
Как использовать GDT быстрее, чем записывать в регистр? Кроме того, я предполагаю, что цена обновления FS и GS оплачивается только при переключении между процессами, а это означает, что нет никаких дополнительных затрат на ввод ядра через системный вызов, когда никакой другой процесс не планируется запустить?