是否可以在线程之间共享寄存器?

时间:2013-05-23 15:51:32

标签: linux multithreading x86 arm mips

我知道当OS / Hardware在执行不同线程之间切换它管理存储/恢复每个线程的上下文时,不过我不知道很多细节。我的问题是:是否有可用于在线程之间共享信息的寄存器?在x86? MIPS?臂?等等,。 Linux呢?窗户?

关于如何做到这一点的任何建议都是非常苛刻的。

3 个答案:

答案 0 :(得分:1)

有些处理器架构在上下文切换期间未存储某些寄存器。从内存来看,29K有一些这样的寄存器,它们基本上只是全局变量 - gr112 .. gr115来自网络。现在,这是一台拥有192个物理寄存器的机器,因此为了这种目的而牺牲一些并不奇怪。

我知道x86和x86-64使用“所有寄存器”这一事实,ARM也是如此。根据我的收集,MIPS也没有“为用户保留”的任何寄存器。这适用于Windows和Linux操作系统。

对于任何具有少量寄存器(小于或等于32)的处理器,我会说“浪费”寄存器是全局的,只是为了保留某些其他线程/进程可能想要读取的值是浪费资源 - 如果该寄存器用作编译器可用的通用寄存器,则通用代码将运行得更快。

答案 1 :(得分:1)

如果您正在编写系统中的所有代码,您可以将寄存器专用于您想要的任何目的,但受限于任何专用于特定功能的寄存器将无法用于任何其他目的。有一些非常特殊的情况,这可能值得做;这些程序看起来非常简单,但需要非常快速地运行。像gcc这样的一些编译器可以通过允许程序员指定特定寄存器来促进这种使用,除非明确请求,否则它所生成的代码不应用于任何目的。通常,因为通过限制编译器可以使用的寄存器的数量来减少编译代码的效率,所以简单地使用静态定义的存储器位置来在线程之间交换信息将更有效。虽然无法像寄存器那样快速访问存储器位置,但可以为各种目的保留许多存储器位置,而不会影响编译器优化寄存器使用的能力。

我在ARM上看到的使用专用寄存器的一种情况是有用的,即需要大量多种方法来共享公共静态数据结构。指定应始终假定某个寄存器保存指向该数据结构的指针,并且该代码必须永远不能修改它,从而消除了在访问其中的项之前加载该结构的地址的代码的需要。如果要在线程之间共享信息,这可能是一种有用的方法,因为访问任意静态位置通常需要PC相对负载来获取地址,然后加载实际数据;拥有专用寄存器可以消除其中一个负载。

答案 2 :(得分:0)

乍一看,你的问题似乎很合理。其他人试图直接回答这个问题。首先,我们有两个相当模糊的概念,

  1. 线程
  2. 寄存器
  3. 如果你与 Ada 人谈话,他们会因缺乏 linux posix 线程的定义而感到害怕。他们更像是 Java的绿色线程,具有非常确定的调度。我认为你的意思是处理器速度很快的线程,比如 posix 线程。

    2 nd 问题是什么是寄存器?对于大多数人来说,它们仅限于在CPU的指令集中硬编码的8,16或32个寄存器。通常可以通过其他方式访问第二类寄存器。主要是它们非常快。

    反向

    你的问题的反面很常见。如何为每个线程将寄存器设置为不同的值。通用寄存器由编译器使用,编译器的 ABI 非常熟悉 OS上下文切换代码。可能不太清楚的是,每次线程运行时,堆栈寄存器的高位之类的东西可能是常量;但每个线程都不同。也就是说每个线程都有自己的堆栈。

    使用ARM Linux时,会使用一个特殊的协处理器寄存器来实现thread local storage协处理器寄存器的访问速度比通用寄存器慢,但速度仍然很快。这让我们了解了流程和线程之间的区别。

    线程流行

    进程具有完全不同的内存布局。即, mmu 页面表切换不同的进程。对于线程,寄存器集可能不同,但所有常规内存在线程之间共享。因此,在进行线程编程时会有很多互斥锁

    现在,考虑CPU缓存。它就像通用寄存器一样是超快速内存。唯一的区别是解决它所需的指令量。

    答案

    所有操作系统和CPU都已经拥有了!每个线程共享内存,该内存缓存。在 cache 的两个线程中加载全局变量的速度接近寄存器访问速度。由于您建议的线程寄存器只能保存一个指针,您需要取消引用它以访问一些更大的实体。加载全局变量几乎一样快,编译器可以自由地将它放在它喜欢的任何寄存器中。编译器也可以在不需要此访问的例程中使用这些寄存器。因此,即使有一个操作系统保留通用寄存器为线程之间的相同,但对于非常小的它只会更快>一组应用程序。