Подтвердить что ты не робот

Последствия для контекстных переключателей для баз 64-разрядных сегментов

Меня смущает формулировка на странице руководства 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 оплачивается только при переключении между процессами, а это означает, что нет никаких дополнительных затрат на ввод ядра через системный вызов, когда никакой другой процесс не планируется запустить?

4b9b3361

Ответ 1

Ничего себе, это было задано в декабре, и никто не ответил на это? Некоторые из этого вы, возможно, уже знаете, и я приношу свои извинения, если так.

Это просто потому, что шаги для выполнения wrmsr медленны. Легче и быстрее просто загружать регистры сегментов при переключении задач.

На очень современных процессорах Intel добавление команд "rdfsbase", "wrfsbase", "rdgsbase" и "wrgsbase" обеспечивает прямой доступ к базовым регистрам FS и GS с гораздо меньшими трудностями, чем раньше. Фактически, ядро ​​может разрешить их использование из пользовательского режима, если ему это нравится. Возможно, вы захотите проверить, используют ли современные ядра Linux преимущество wrfsbase, чтобы сделать ненужным выделение области TLS ниже 4 ГБ.

Я не знаю, как это работает в Linux, но Windows NT, начиная с Windows 7, имеет диспетчеризацию потоков пользовательского режима в качестве дополнительной функции для разработчиков приложений. Как и в Linux и Mac OS X, Windows реализует поточно-локальное хранилище на x86, используя базовый адрес сегментных регистров (GS в x86-64 Windows). Эта функция похожа на волокна, за исключением того, что программа может переключать свой собственный контекст потока с другим способом, который также распознается ядром.

Планирование пользовательского режима в Windows реализовано путем создания LDT с сегментами, указывающими на блоки TLS (называемые "Блоки среды нитей" или TEB, в Windows) для каждого потока планирования. Пользовательский режим может затем переключать потоки, перезагружая базу GS в дополнение к контекстному коммутатору. Для этого требуется, чтобы TEB были ниже 2 ^ 32, как в примечании к производительности Linux arch_prctl - в противном случае для пользовательского режима планирования требовался бы вызов ядра NT каждый раз, когда он переключился на другой поток, чтобы сделать wrmsr, победив всю точку планирования пользовательского режима.

В Windows 8.1 была добавлена ​​поддержка wrgsbase, и она также включена для пользовательского режима. Планирование пользовательского режима в 8.1 использует wrgsbase вместо перезагрузки сегмента GS и LDT, если у него есть процессор.