CITKIT.ru - свободные мысли о свободном софте
Деловая газета CitCity.ru Библиотека CITForum.ru Форумы Курилка
Каталог софта Движение Open Source Дискуссионный клуб Дистрибутивы Окружение Приложения Заметки Разное
15.12.2017

Последние комментарии

ОСТОРОЖНО: ВИНДОФИЛИЯ! (2250)
24 December, 22:53
Kubuntu Feisty (15)
24 December, 18:42
Один на один с Windows XP (3758)
24 December, 11:46

Каталог софта

Статьи

Дискуссионный клуб
Linux в школе
Open Source и деньги
Open Source и жизнь
Windows vs Linux
Копирайт
Кто такие анонимусы
Лицензии
Нетбуки
Нужен ли русский Linux?
Пользователи
Дистрибутивы
Идеология
Выбор дистрибутива
Archlinux & CRUX
Debian
Fedora
Gentoo
LFS
LiveCD
Mandriva
OpenSolaris
Slackware
Zenwalk
Другие линуксы
BSD
MINIX
Движение Open Source
История
Классика жанра
Окружение
shell
Библиотеки UI
Графические среды
Шрифты
Приложения
Безопасность
Управление пакетами
Разное
Linuxformat. Колонки Алексея Федорчука
Заметки
Блогометки
Файловые системы
Заметки о ядре

Дистрибутивы :: BSD :: DragonFly BSD

DragonFly - модель легковесных нитей ядра

Модель легковесных нитей ядра

В основе DragonFly лежит модель легковесных нитей (threads) ядра (LWKT, Light Weight Kernel Threading). Для каждого процесса в системе имеется ассоциированная с ним нить, а большинство процессов ядра - это фактически всего лишь чистые нити. Например, демон pageout (вытеснения страницы из ОЗУ) - это чистая нить без контекста процесса.

У модели LWKT имеется ряд ключевых особенностей, независимых от архитектуры. Эти особенности были разработаны для устранения или сокращения конкуренции между процессорами.

1. Для каждого процессора в системе имеется свой собственный, автономный LWKT-планировщик (sheduler). Нити умышленно привязываются к своим процессорам и могут быть перемещены на другой процессор только при наступлении некоторых особых условий. Любая операция планирования LWKT на конкретном процессоре может выполняться только непосредственно на этом процессоре. Это значит, что LWKT-планировщик может производить планирование и переключение нитей без каких бы то ни было блокировок. Никаких блокировок на уровне многопроцессорной системы, ничего, кроме простого критического участка.

2. Нить никогда не будет вытеснена на другой процессор, пока она выполняется в ядре, и нить никогда не будет перемещаться между процессорами, когда она блокирована. Планировщик пользовательского уровня может переместить нить, выполняющуюся пользовательском режиме. Нить никогда не будет переключена через вытеснение непрерываемой нитью. Если прерываемая нить вытесняет текущую нить, то в момент, когда прерываемая нить завершает свое выполнение или блокируется, вытесненная нить возобновляет выполнение независимо от своего состояния с точки зрения планировщика. Например, нить может быть вытеснена после вызова lwkt_deschedule_self(), но это произойдет раньше, чем она реально отключится. И это правильно, потому что управление будет возращено ей непосредственно после того, как прерываемая нить поток завершит свое выполнение или блокируется.

3. Из того, что сказано в п.2, следует, что нить может кэшировать информацию, полученную через процессорную структуру глобальных данных без потребности в получении каких-либо блокировок и, если известно, что эта информация не была затронута прерываниями, надобности вхождения в критический участок. Это позволяет реализовывать процессные практически без накладных расходов.

4. Процессор, который пытается планировать нить, принадлежащую другому процессору, для выполнения операции будет посылать целевому процессору сообщения основанные на IPI. Эти сообщения асинхронны по умолчанию, и хотя IPI могут обладать некой латентностью, они не обязательно растрачивают вхолостую циклы по этой причине. Нити могут заблокировать подобные операции путем входа в критический участок, что фактически и делает LWKT-планировщик. Вход в критический участок и выход из него считаются экономными операциями и не требуют ни блокировки, ни выполнения команд блокирования шины.

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

В дополнение к этим ключевым особенностям, модель LWKT позволяет производить вытеснение по FAST-прерываниям И вытеснение по нитиевым прерываниям. FAST- прерывания могут вытеснять текущую нить, когда она не находится в критическом участке. Нитиевые прерывания также могут вытеснять текущий поток. Система LWKT будет переключаться в режим нитиевых прерываний, а потом - обратно в исходное состояние, когда нитиевое прерывание блокируется либо завершает работу. Действие функций IPI очень похоже на действие FAST-прерываний. В DragonFly это в полной мере используется в SYSTIMERS API для распределения прерываний hardclock() и statclock() между всеми процессорами.

Подсистема IPI для работы с сообщениями

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

Сообщения IPI функционируют аналогично FAST-прерываниям... в том смыслу, что они вытесняют все, что выполняется на целевом процессоре (с учетом критических участков), выполняются сами, а потом возобновляется то, что выполнялось ранее. По этой причине функциям IPI не разрешается блокировать что бы то ни было никоим образом. Сообщения IPI используются для таких целей как планирование нитей и свободной памяти, принадлежащих другим процессорам.

Подсистема IPI интенсивно используется не менее чем в шести основных подсистем LWKT, включая внутрипроцессорное планирование нитей и подсистемы обмена сообщениями. Поскольку система IPI является прирожденной для DragonFly, в ней не требуется и не используется механизм Big Giant Lock (как во FreeBSD). Поэтому все функции, основанные на IPI, должны быть МР-безопасными (и они таковыми являются).

Основанная на IPI подсистема синхронизации процессоров

В модели LWKT используется обощенный, машиннонезависимый API синхронизации процессоров. Этот API может использоваться для перевода целевых процессоров в известное состояние, пока ведется работа с чувствительной структурой данных. Этот интерфейс, прежде всего, применяется при обновлении таблиц страниц устройства управления памятью (MMU). Например, небезопасно проверять и очищать бит модификации в элементе таблицы страниц, а потом удалять этот элемент, даже сохранив соответствующую блокировку. Это потому, что пользовательский процесс, выполняющийся на другом процессоре, может обращаться к этой таблице и изменять ее, из-за чего возникнет соревнование между образом буфера быстрого преобразования адреса (TLB) на целевом процессоре и вашими попытками очистить элемент таблицы страниц. Правильное решение состоит в том, чтобы сначала перевести в известное состояние все процессоры, которые могут произвести выталкивание из TLB в элемент таблицы страниц (т.е. все процессоры в маске pm_active pmap'а), провести модификацию, после чего освободить процессоры с запросом на объявление недействительными их TLB.

API, реализованное в DragonFly, свободно от взаимных блокировок. Действия по синхронизации нескольких процессоров могут выполняться параллельно, и это распространяется на все нити, которые обрабатывают событие ссинхронизации, на время этой обработки. Даже при наличии этой гибкости, поскольку интерфейс синхронизации процессоров работает в контролируемой среде, функции обратного вызова (callback) работают подобно функциям используемым в подсистеме сообщений IPI.

Сериализующие маркеры

Сериализующий маркер (serializing token) может удерживаться одновременно несколькими нитями. Для нити, удерживающей сериализующий маркер, гарантируется, что одновременно с ней не будет выполняться ни одна нить с тем же маркером.

Нить может удерживать любое число сериализующих маркеров.

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

Теоретически при использовании механизма сериализующих маркеров нет неразрешимых проблем со взаимной блокировкой. Тем не менее, в начальной реализации могут проявляться проблемы, связанные с удержанием нескольких маркеров.

Сериализующие маркеры может также использоваться для защиты нитей от вытеснения прерываниями, стремящимися получить тот же маркер. Этот эффект несколько отличается от механизма Big Giant Lock (также известной под названием МР-блокировки), который не обеспечивает блокировку для защиты от вытеснения прерываниями на том же самом процессоре. Важно заметить, что атомарность маркера сохраняется в условиях вытеснения, даже если вытеснение предполагает временное переключение на другую нить. Для того, чтобы сохранить атомарность маркера, нет необходимости входить на уровень spl() либо в критический участок.

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





Новости:

Все новости на CitCity.ru

Компании месяца

 
Последние комментарии
Почему школам следует использовать только свободные программы (101)
20 Декабрь, 14:51
ОСТОРОЖНО: ВИНДОФИЛИЯ! (2250)

24 Декабрь, 22:53
Linux в школе: мифы про школу и информатику (334)
24 Декабрь, 22:43
Kubuntu Feisty (15)
24 Декабрь, 18:42
Software is like sex: it's better when it's free.
©Linus Torvalds