Linux 4.18 представил restartable sequences (rseq) — механизм, который позволяет создавать потокобезопасные структуры данных без блокировок и атомарных операций. Работает это так: поток регистрирует в ядре 32 байта TLS-памяти. Пока выполняется критическая секция (обычно 10 инструкций ассемблера), ядро не прерывает поток — а если прерывает, то принудительно перебрасывает его на abort-обработчик. Вся связь с ядром идёт через разделяемую память, поэтому накладные расходы минимальны.
Justine (автор Cosmopolitan Libc) провела замеры на трёх машинах. На её дешёвом Raspberry Pi 5 (4 ядра) rseq ускорил её malloc() в 3 раза по сравнению с выделением отдельного mspace на поток. На System76 Thelio Astra с Ampere Altra (128 ядер по 3 ГГц, стоит $4834) rseq дал ускорение в 34 раза. На AMD Threadripper Pro 7995WX (96 ядер, $17 628) — в 43 раза. А если сравнивать с наивным мьютексом из glibc, разница достигает миллиона раз по загрузке CPU.
Для счётчика посещений (хит-каунтера) автор сравнила пять подходов. С мьютексом glibc на Threadripper получилось 161k операций/с по CPU, с атомиками — 440k, с шардированием (разные списки на каждое ядро) — 20,5 млн, с rseq — 1,65 млрд, а с привязкой потоков к ядрам (affinity) — 174,5 млрд. На Ampere результаты похожи, но ARM показал более быстрые атомики (ldadd без барьеров). rseq превратил 3-гигагерцовый CPU в условный 33-гигагерцовый — по крайней мере для этой задачи.
В статье приведён полный код push/pop для шардированного связного списка на ассемблере x86-64 и ARM64. Автор использует GNU extended asm с метками и .pushsection для размещения rseq_cs в специальной секции. Код можно скомпилировать компилятором cosmocc. rseq пока требует ручного ассемблерного кода — LLM, по мнению автора, с этим не справятся. Но она уверена, что в будущем все ОС и языки программирования добавят поддержку rseq.
Системный вызов rseq() разработали Paul Turner и Andrew Hunter из Google, а также Mathieu Desnoyers из EfficiOS. Сейчас rseq используется в tcmalloc, jemalloc, glibc и Cosmopolitan Libc. Автор также отмечает, что Ampere наконец-то воплотил мечту RISC — 128 ядер по доступной цене, и ARM в некоторых бенчмарках обходит дорогой x86.