Как вы останавливаете поток и сбрасываете его регистры в стек? - PullRequest
5 голосов
/ 10 января 2012

Я создаю параллельный алгоритм восстановления памяти в C ++. Периодически необходимо проверять стеки выполняемых потоков-мутаторов, чтобы я мог видеть, какие ссылки эти потоки в настоящее время хранят. В процессе этого мне нужно также проверить регистры потока мутатора, чтобы проверить любые ссылки, которые могут быть там.

Очевидно, что многие JVM и C # vm не испытывают проблем с выполнением этого в рамках своих циклов сборки мусора. Однако я не смог найти окончательного решения этой проблемы.

Я не могу полностью отделить то, что происходит в сборщике мусора в Богеме, чтобы проверить корневой набор, если вы можете (или знаете, как это делается), я бы очень хотел знать.

В идеале я мог бы вызвать прерывание потока мутатора и выполнить часть кода обработчика, который сообщит о его ПК, а также сбросит все ссылки на основе регистров в стек, а затем, возможно, поможет завершить цикл сбора. Я полагаю, что большинство компиляторов в большинстве систем автоматически сбрасывают регистры при вызове обработчиков прерываний или сигналов, но мне не ясно специфика или то, как получить доступ к этим данным. Кажется, что отдельные стеки могут быть использованы для обработки прерываний и сигналов. Кроме того, я не могу найти информацию о том, как настроить таргетинг на конкретный поток или как отправить сигнал. Windows, похоже, в любом случае не поддерживает эту форму сигнализации, и я хотел бы, чтобы моя система работала как на Linux, так и на Windows на процессорах x86-64.

Edit: SuspendThread () используется в некоторых ситуациях, хотя безопасные точки кажутся предпочтительными. Есть идеи, почему? Есть ли способ справиться с длительными ожиданиями ввода-вывода или другими ожиданиями возврата кода ядра?

Ответы [ 2 ]

3 голосов
/ 10 января 2012

Я подумал, что это очень интересный вопрос, поэтому немного углубился в него.Оказывается, что JVM Hotspot использует механизм, называемый «безопасными точками», который заставляет потоки JVM совместно останавливать себя, чтобы GC мог начать.Другими словами, поток, инициирующий GC, не принудительно останавливает другие потоки, другие потоки добровольно приостанавливают себя с помощью различных хитрых механизмов.

Я не верю, что JVM сканирует регистры, потому что безопасная точка определяется такчто все корни известны (я предполагаю, что это означает в памяти).

Для получения дополнительной информации см .:

  • Глоссарий HotSpot - который определяет безопасные точки
  • safepoint.cpp - источник в HotSpot, который реализует безопасные точки
  • Слайд-колода , которая описывает безопасные точки более подробно (см. 10 слайдов или около того)

Что касается вашего желания «прервать» все потоки, то, согласно слайд-деке, на которую я ссылался выше, приостановка потоков «ненадежна в Solaris и Linux, например, в случае ложных сигналов».Я не уверен, какой механизм вообще существует для приостановки резьбы, на которую ссылаются слайды.

1 голос
/ 10 января 2012

В Windows вы должны быть в состоянии сделать это, используя SuspendThread (и ResumeThread) вместе с GetThreadContext (как упоминал Ганс).Все эти функции обрабатывают конкретный поток, на который вы нацелены.

Чтобы получить список всех потоков в текущем процессе, см. this (toolhlp32 работает на x64, несмотря на его плохойсхема именования ...).

Интересно, что одним из способов сброса регистров в стек на x86 является использование инструкции сборки PUSHAD.

...