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

时间:2012-01-10 02:54:00

标签: c++ multithreading memory-management concurrency garbage-collection

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

显然,许多JVM和C#vm在执行此操作时都没有问题,因为它们是垃圾收集周期的一部分。但是,我无法找到解决此问题的最终解决方案。

我无法理解Bohem垃圾收集器中发生的事情,以便检查根集,如果可以(或知道它是如何完成的),我真的很想知道。

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

编辑: SuspendThread()在某些情况下使用,虽然安全点似乎是首选。有什么想法吗?有没有办法处理持久的I / O等待或其他等待内核代码返回?

2 个答案:

答案 0 :(得分:3)

我认为这是一个非常有趣的问题,所以我稍微挖了一下。事实证明,Hotspot JVM使用一种称为“安全点”的机制,这种机制使JVM的线程协同工作,所有这些机制都会自行停止,以便GC可以开始。换句话说,启动GC的线程不会强制停止其他线程,其他线程会自动通过各种聪明的机制暂停自己。

我不相信JVM会扫描寄存器,因为定义了一个安全点,以便知道所有根(我认为这意味着在内存中)。

有关详细信息,请参阅:

关于你“中断”所有线程的愿望,根据我上面提到的幻灯片,线程暂停“在Solaris和Linux上是不可靠的,例如,虚假信号”。我不确定滑块所指的线程悬挂甚至存在什么机制。

答案 1 :(得分:1)

在Windows上,您应该能够使用SuspendThread(和ResumeThread)以及GetThreadContext完成此操作(正如汉斯所提到的)。所有这些函数都会处理您要定位的特定线程。

要获取当前进程中所有线程的列表,请参阅this(toolhlp32适用于x64,尽管其命名方案错误...)。

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