кстати, раз уж я временно с ядром сожительствую… сделать, что ли, потокобезопасный аллокатор/GC? повторять ABB я нужды не вижу, так что попытки рисовать или прочим непотребством из потоков заниматься всё порушат, конечно. но сделать mailbox'ы, и возможность зашедулить action для исполнения в главном потоке — отчего бы и да.
конечно, в идеале хватило бы просто `fork()` и IPC. но есть ма-а-аленькая проблема: безопасный `fork()` невозможен. то есть, в принципе ваще. то есть, возможен, но для этого надо отказаться от всех системных библиотек (включая libc), и делать жёсткий статический бинарь. иначе нет никакой гарантии, что какая-то идиотская библиотека не стартанёт из себя поток — и приехали.
если бы не вышеописаное, то можно было бы просто форкаться, когда нужно, да и всё (а винда идёт в). но имеем что имеем, и иногда потоки полезны. единственная проблема — в пинусах, распронаедрит их напополам, нет никакого аналога виндового `SuspendThread()`. потому что авторы пинусов уверены, что знают все возможные задачи на свете, и среди них нет ни одной, которая потребовала бы такого Очень Небезопасного API. то, что это единственный нормальный способ получить снапшот софтины для GC — их не волнует, потому что о такой задаче в их ПТУ для умственно осталых не рассказывали.
конечно, через задний проход задача решается (в пинусах всё делают через задний проход, чтобы не заскучать). но для этого надо зарезервировать себе один системный сигнал — из двух доступных USR. два. на всё. без какого-либо механизма получить unique signal id. угадайте, есть ли на свете библиотеки, которые
уже используют SIGUSR1 и SIGUSR2 для своих целей.
конечно, кому-то в межушный ганглий пришла идея, что софту могут понадобиться свои личные сигналы, и они изобрели real-time signals. зарезервировали номера, и — как полагается — не сделали никаких общих механизмов для резервирования этих номеров в софте. потому что POSIX — это про то, как никогда не надо делать что-то практически полезное.
самое смешное, что в пинусах есть SIGSTOP и SIGCONT… но они тормозят всю софтину сразу. при некоторых условиях ними можно тормознуть и поток, но в принципе нигде не описано толком как, и будет ли это нормально работать.
самое близкое к независимому от сигналов решение — сделать `clone()` (сискол), послать родителю SIGSTOP, просканировать все его потоки, прогнать GC в форке, послать SIGCONT и помереть. отвратительно.
правда, с клоном можно провернуть другую штуку: псевдопараллельный GC. если у нас закончилось место в кластерах, но есть подходящий в кэше свободных — мы пинаем клон на сборку (клонируем в режиме COW), а сами берём свободный кластер и продолжаем. таким образом GC происходит в другом процессе, а когда он закончил — сигнализирует папе, и мы мержим списки свободного места. это я писать не буду, конечно: у меня нет задач, где такое важно.
на самом деле можно вообще сделать инкрементальный GC, чуть-чуть модифицировав компилятор. если использовать
quad-color GC вместо классического 3-color, то оно даже будет не очень сильно тормозить. но мне откровенно лень, и я это бесплатно делать не буду. ;-)
p.s.: quad-color GC я уже пилил у себя в одном скриптовом язычке. ну… он работает.