OberonCore https://forum.oberoncore.ru/ |
|
E11: Спец. тип в Kernel для областей с особой маркировкой GC https://forum.oberoncore.ru/viewtopic.php?f=116&t=6070 |
Страница 1 из 1 |
Автор: | Илья Ермаков [ Понедельник, 19 Июнь, 2017 20:31 ] |
Заголовок сообщения: | E11: Спец. тип в Kernel для областей с особой маркировкой GC |
Сегодня Евгений Эдуардович выложил сборку ББ OberonCore с некоторыми обновлениями: viewtopic.php?p=101136#p101136 Одно из изменений ядра - из нашей платформы приложений, для поддержки кооперативной многозадачности (которую пока что не публикуем). При переключении задач сохраняются их стеки - и сборщик мусора должен маркировать структуру, где сохранён стек неактивной задачи. Собственно, с этим же столкнулись коллеги, у которых есть аналогичная многозадачность, режим сопрограмм: viewtopic.php?f=31&t=5219 Как это решено у нас - и как вошло в сборку OberonCore: - введён специальный абстрактный базовый тип SpecialArea Код: SpecialArea* = POINTER TO ABSTRACT RECORD opts*: SET END; Любой тип, в области данных которого хранятся адреса, должен быть расширен от SpecialArea. Это, например, страница списков, где сохраняются стеки. Типа: Page = POINTER TO RECORD (Kernel.Special) next: Page; data: ARRAY 512 OF BYTE END. При наличии в opts флага Kernel.conservMark сборщик будет выполнять консервативную маркировку тела записи. Второй режим маркировки - не консервативный, а с использованием битовой карты размещения указателей. Это гораздо эффективнее (хотя и не может быть использовано для хранения стеков). У нас это используется для байтовых буферов, в которые можно записывать и указатели, становящиеся якорями. Это удобно, например, для очереди, в которую пишутся RECORD-ы, имеющие поля-указатели, на что-то ссылающиеся (допустим, на объект с какой-то метаинформацией, хотя такие объекты обычно и заякорены где-то ещё - но мы же не можем позволить записывать RECORD с указателем на страх и риск). Для такого режима маркировки свой тип данных также расширяется от Page - и добавляется следующий заголовок: Код: Page = POINTER TO RECORD (Kernel.Special) prev, next: Page; dataLen: INTEGER; map: ARRAY 32 OF SET; data: ARRAY 4096 OF BYTE END; Все понимают, что соотношение между размером map-а и размером data должно быть: LEN(map) = LEN(data) DIV 4 DIV 32. Далее вы выставляете правильный dataLen, а в opts выставляете флаг Kernel.markByMap. Правила картографии: - когда записываете в данные data какой-нибудь RECORD с указателями, то, как и в ОЗУ, сначала записываете тег Kernel.Type. - в битовой карте бит для слова с тегом НЕ ПОМЕЧАЕТСЯ, он 0. - далее записываете RECORD, кратно 4 байт, все слова в карте помечаете как 1. (таким образом, когда идёт один RECORD за другим, в битовой карте начало каждого RECORD-а однозначно определяется по фронту 0->1). Доп. фишка: ваши странички могут быть связаны в список по prev и next - и тогда RECORD вообще может записываться разрывно (часть на одной странице, часть - на следующей или нескольких следующих), маркировка его будет выполняться корректно. |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |