上下文切换对64位段基的性能影响

has*_*ste 22 c linux performance x86-64 cpu-registers

我对手册页中的措辞感到困惑arch_prctl(2).具体来说,它指出:

64位段基的上下文切换相当昂贵. 通过在内核2.5或更高版本中使用modify_ldt(2)或使用set_thread_area(2)系统调用设置LDT,使用段选择器设置32位基址可能是更快的替代方法.只有当您想要设置大于4GB的基数时,才需要arch_prctl().可以使用带有MAP_32BIT标志的mmap(2)来分配前2GB地址空间中的内存.

这是否意味着使用此系统调用的进程的上下文切换将受到性能损失或具有哪些确切含义?

查看Linux内核的源代码后,似乎对于<4 GiB的地址使用LDT,而> 4 GiB地址使用特定于模型的寄存器.

来自do_arch_prctl:

case ARCH_SET_FS:
        /* handle small bases via the GDT because that's 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;
Run Code Online (Sandbox Code Playgroud)

如何使用GDT比写入寄存器更快?此外,我假设更新FS和GS的价格仅在流程之间切换时支付,这意味着当没有其他流程计划运行时,通过系统调用进入内核没有额外成本?

Myr*_*ria 3

哇,这个问题十二月份就有人问了,没人回答吗?其中一些您可能已经知道,如果是这样,我深表歉意。

只是因为做wrmsr的步骤很慢。任务切换时只加载段寄存器会更容易、更快捷。

在非常现代的英特尔处理器上,添加“rdfsbase”、“wrfsbase”、“rdgsbase”和“wrgsbase”指令允许直接访问 FS 和 GS 的基址寄存器,难度比以前小得多。事实上,如果内核愿意的话,可以允许它们在用户模式下使用。您可能想要检查现代 Linux 内核是否利用 wrfsbase 来无需分配低于 4 GB 的 TLS 区域。

我不知道Linux上的情况如何,但是从Windows 7开始的Windows NT将用户模式线程调度作为应用程序开发人员的可选功能。与 Linux 和 Mac OS X 中一样,Windows 使用段寄存器的基地址(x86-64 Windows 中的 GS)在 x86 上实现线程本地存储。此功能类似于纤程,不同之处在于程序可以通过内核也识别的方式将自己的线程上下文与另一个线程上下文切换。

Windows 中的用户模式调度是通过为每个可调度线程创建一个 LDT 来实现的,其中的段指向 TLS 块(在 Windows 中称为“线程环境块”或 TEB)。除了上下文切换之外,用户模式还可以通过重新加载 GS 库来切换线程。这要求 TEB 低于 2^32,如 Linux 的 arch_prctl 性能说明中所示 - 否则,用户模式调度将需要在每次切换到不同线程时调用 NT 内核以执行 wrmsr,从而破坏了整个要点用户模式调度。

在 Windows 8.1 中,添加了对 wrgsbase 的支持,并且也为用户模式启用了它。8.1 中的用户模式调度使用 wrgsbase 而不是 GS 段重新加载和 LDT(如果 CPU 有的话)。