Существует ли заголовок linux для хэш-таблицы с корзинами, защищенными от спин-блокировки?
Я пишу код, который редко создает / удаляет объекты (до нескольких тысяч), но очень часто модифицирует их в контексте мягкого IRQ. Эти объекты также редко читаются (и, вероятно, также редко изменяются) из контекста задачи (через procfs: файл на объект). В настоящее время мой код содержит глобальные блоки данных для каждого процессора, каждый из которых защищен спин-блокировкой. Такой блок содержит хеш-таблицу фиксированного размера для хранения объектов.
Очевидно, что текущий дизайн не является оптимальным, особенно при очень высоких нагрузках на обновление объектов: чтение объектов из procfs приведет к потере данных при обновлении мягких IRQ. Мне нужно переписать схему синхронизации, чтобы избавиться от глобальных блокировок. Самый очевидный выбор - иметь спин-блокировку для каждого хэш-таблицы - он должен хорошо масштабироваться. Проблема в том, что мне, вероятно, понадобится использовать мою собственную реализацию хеш-таблицы или, по крайней мере, переопределить несколько макросов верхнего уровня (не нашло их в linux/hashtable.h для блоков с защитой от спин-блокировки). Должен ли я также взглянуть на хеш-таблицу с поддержкой RCU (но у меня нет четкого понимания этого подхода синхронизации)?
1 ответ
Контейнеры с защитой от блокировки объявляются в заголовке linux / list_bl.h. Они используют младший бит указателя головы в качестве бита блокировки.
Защищенный RCU доступ к корзине определяется с помощью других функций хеш-таблицы в заголовке linux / hashtable.h (они имеют _rcu
суффикс).
Выбор между замками и RCU остается за вами. Обратите внимание, что сам RCU не может разрешить конфликты модификации-модификации. И это помогает в основном для часто читаемых данных, что, кажется, не ваш случай.
Как только одна функция блокировки - hlist_bl_lock
- объявлен для struct hlist_bl_head
и эта функция не знает о irq, дополнительные действия должны выполняться, когда хеш-таблицу можно использовать в irq или нижних половинах:
spin_lock_irqsave:
local_irq_save(flags); hlist_bl_lock(...);
spin_unlock_irqrestore:
hlist_bl_unlock(...); local_irq_restore(flags);
spin_lock_bh:
local_bh_disable(); hlist_bl_lock(...);
spin_unlock_bh:
hlist_bl_unlock(...); local_bh_enable();