如何决定为操作系统任务切换保留的寄存器?



当任务切换在操作系统中发生时,如何决定应该保留哪些寄存器?

这纯粹是由硬件架构决定的吗?或者也包括操作系统的实现?

我曾经在ARM架构上做过一些naïve实现,保留了所有R1 ~ R15寄存器(如果我没记错的话)。但这似乎太多了。

我还尝试了x86硬件任务切换支持,TSS段涵盖了许多性能不佳的寄存器。

我猜是操作系统的设计理念,特别是任务状态的实现应该决定这个。但我不确定是否有任何最佳实践或惯例。或其他因素。

当任务切换在操作系统中发生时,如何决定应该保留哪些寄存器?

通常情况下,大多数调度器将用高级语言(例如C)编写,而低级任务切换代码将写成小型汇编语言函数(而不是内联汇编),因为没有统一的方法来预测编译器可能对堆栈和局部变量做什么。

因为这个;哪个注册低级汇编函数需要保存/恢复取决于编译器想要使用的ABI(调用约定)。例如,System V AMD64 ABI规定,被调用者必须保留RBX、RSP、RBP和R12到R15(如果不用作返回参数,可以将RAX、RCX、RDX和R8丢弃到R11)。

这取决于操作系统的性质。例如,可以设计一个操作系统,其中内核像一个单独的任务一样运行,任何导致从用户空间切换到内核空间的操作都像任务切换,并且必须在执行任何更高级别的内核代码之前保存所有内容。

对于操作系统选择保留哪些注册,理论上有很大的回旋余地。为了"安全"操作系统将保存所有用户和/或内核线程可以访问的寄存器。我们通常会想到R0 R1 Rx…(ARM, MIPS, . etc)或RAX,RBX,…(x86)寄存器需要保存。然而,硬件浮点和矢量指令(x86 AVX)也可能需要保留。

这通常是操作系统的实现有回旋余地。我们可以简单地保守起见,保留所有浮点和矢量指令寄存器。但是,如果线程不使用这些寄存器,保存未使用的寄存器会减慢上下文切换的速度。更不用说处理器家族可能具有相同的核心指令和寄存器,但可选的浮点或向量扩展。因此,如果线程使用浮点指令或向量指令,一些操作系统支持在线程中标记,这样操作系统就知道要保留哪些额外的寄存器。

最新更新