如何停止线程并将其寄存器刷新到堆栈中

How do you stop a thread and flush its registers into the stack?

本文关键字:刷新 堆栈 寄存器 何停止 线程      更新时间:2023-10-16

我正在C++中创建一个并发内存回收算法。需要定期检查正在执行的赋值线程的堆栈,这样我就可以看到线程当前持有的引用。在执行此操作的过程中,我还需要检查赋值线程的寄存器,以检查其中可能存在的任何引用。

很明显,许多JVM和C#vm在垃圾回收周期中这样做是没有问题的。然而,我还没能找到解决这个问题的最终办法。

为了检查根集,我无法完全梳理Bohem垃圾收集器中发生了什么,如果可以的话(或者知道它是如何完成的),我真的很想知道。

理想情况下,我可以使赋值线程中断,并执行一段处理程序代码,报告它的PC,还可以将任何基于寄存器的引用刷新到堆栈中,然后可能帮助完成收集周期。我相信大多数系统中的大多数编译器在调用中断或信号处理程序时都会自动刷新寄存器,但我不清楚具体细节,也不清楚如何访问这些数据。中断和信号处理程序似乎可以使用单独的堆栈。此外,我找不到任何关于如何针对特定线程或如何发送信号的信息。Windows似乎无论如何都不支持这种形式的信号,我希望我的系统在Linux和Windows的x86-64处理器上运行。

编辑:SuspendThread()在某些情况下使用,尽管安全点似乎是首选。有什么想法吗?有什么方法可以处理长时间的I/O等待或内核代码返回的其他等待吗?

我觉得这是一个非常有趣的问题,所以我深入研究了一下。事实证明,Hotspot JVM使用了一种称为"安全点"的机制,该机制使JVM的线程协同地全部停止,以便GC可以开始。换句话说,启动GC的线程不会强制停止其他线程,其他线程会通过各种巧妙的机制自动挂起自己。

我不相信JVM扫描寄存器,因为定义了一个安全点,使得所有根都是已知的(我认为这意味着在内存中)。

有关更多信息,请参阅:

  • HotSpot词汇表——定义安全点
  • safepoint.cpp——HotSpot中实现安全点的源
  • 详细描述安全点的幻灯片组(请参阅中的10张左右幻灯片)

关于"中断"所有线程的愿望,根据我上面提到的幻灯片组,线程挂起"在Solaris和Linux上是不可靠的,例如,虚假信号。"我不确定幻灯片所指的线程挂起机制是什么。

在windows上,您应该能够使用SuspendThread(和ResumeThread)以及GetThreadContext(如Hans所述)来完成这项工作。所有这些函数都将句柄带到要作为目标的特定线程。

要获得当前进程中所有线程的列表,请参阅此(toolhlp32适用于x64,尽管其命名方案不正确…)。

感兴趣的是,将寄存器刷新到x86上的堆栈的一种方法是使用PUSHAD汇编指令。