Pull to refresh
149
0
Дмитрий Завалишин @dzavalishin

Архитектор

Send message
Это же не исторический труд… Всего не упомянешь. Хотя, признаться, я хотел про него написать, но вылетело из головы в процессе.
на интеле — ок, но на других архитектурах?
Просится мысль вставить в spin_lock и spin_unlock барьеры. В unlock — записи перед собственно отпиранием (который запись, и, значит, все операции записи внутри запертого спинлока будут видны до того, как другие процессоры увидят отпирание спинлока), в lock — чтения после запирания, чтобы гарантировать, что чтения памяти внутри спинлока не заспекулированы до собственно запирания лока и видят то, что другой процессор записал внутри спинлока.
Поднять можно многое, но в реальности же за соединением — бизнес-логика. По опыту, упираемся не в соединения, не в треды, а в производительность бизнес-логики.
Это Вы написали спинлок. :)

А вот реализация мьютекса. Реальная. https://github.com/dzavalishin/phantomuserland/blob/master/phantom/threads/mutex.c

Попробуйте переписать без спинлока. Обратите внимание на thread_block — ему передаётся запертый спинлок, который отпирается "на той стороне" переключения контекста. И не зря. Иначе может случиться ситуация, когда mutex_unlock попытался разбудить нас до того, как нить реально покинула процессор, и будет беда. Поверьте — будет. Я пробовал.
Он будет со спинлоком. Просто код спинлока придётся написать руками. Впрочем, есть вариант — можно всю работу попробовать организовать lockless, но, боюсь, будет очень тяжко. И ещё: по некоторым причинам, переключение контекста несёт через себя запертый спинлок, который обязательно отпирается только после того, как переключение завершено. Это вообще неясно как сделать без спинлока.

На юзерлевеле этого всего не видно, а в ядре снег тает, и суть вещей проявляется. :)

Если найду время — напишу заметку про контекст свитч и синхронизацию внутри машинерии мьютексов и переключения тредов.
Спор в изрядной степени терминологический. Атомарные операции процессора сами по себе не являются достаточными и удобными — спинлок поверх них реализован не зря.

Но, в принципе, и сам мьютекс можно не делать, как и тред свитч — вписывать каждый раз в код конкретной функуции реализацию mutex_lock и thread switch...

Ну, то есть, логика дробления на уровни абстракции ( atomic CPU instruction, spinlock, mutex) необязательна и спорна. Но — сложилась. У спинлока есть некая семантика, отличная от atomic CPU instructions, и она востребована.

Но, конечно, я не настаиваю — можно сделать вид, что спинлока нет и писать вместо него его код инлайн. :)
А реально ли актуальные? Миллион активных соединений вряд ли отработает сам сервер. Миллиону неактивных, казалось бы, неоткуда взяться… Конечно, по сути, нельзя ограничиваться просто числом и надо описывать распределение — скорость поступления запросов (в секунду), и распределение запросов по шкале стоимости — столько процентов висят без обслуживания, столько обслуживаются коротко (Out of memory), столько — обслуживаются дорого.
Это специфичная реализация семафора, посмотрите следующую статью. Специфичная в том, что значения семафора ограничены 0 и 1, в одном из режимов. Во втором режиме это cond.
Я написал врезку про эту проблему. Ещё раз спасибо!
Вот пример для микроконтроллера. Это туннель TCP/IP-RS485 для atmega128 под EtherNut NutOs, там мьютексы используются для синхронизации работы механизма управление полудуплексом.
Спасибо. Всё ещё хуже. Вот что значит накидать пример навскидку. Атомарной должна быть операция считывание-инкремент-ограничение.
Базовые примитивы в любой ОС, как правило, соответствуют трём перечисленным. Для чего именно они нужны и каковы основные механизмы применения — показано в примерах. Возможно, Вам пока не встретилась задача, которая требует синхронизации. Встретится — возвращайтесь.
"в современных серверных процессорах обычно есть от 8 до 16 ядер, и если мы создаем больше потоков, чем позволяет “железо”, то планировщик ОС перестает справляться с переключением задач с достаточной скоростью."

Я бы поспорил. В 2007-м на машине с 4 ядрами мы гоняли систему с 8000 (восемью тысячами) нитей. Именно в обслуживании http-запросов. Правда, потребовался тюнинг настроек ядра и стандартную jvm заменили на, ЕМНИП, jrockit.
В Ваших словах есть изрядная правота. Но семантическая разница между спинлоком и мьютексом есть. Это переключение контекста. В ядре это важно. В юзерспейсе — Вы правы полностью, есть только мьютекс, и чем он делается — вопрос оптимизации.
Корректировка: работать могут, в описанной выше ситуации новый тред упрётся в запертый спинлок и прокрутится в нём весь свой таймслайс. Просто будут невменяемо неэффективны.
А, Вы о том, что спинлоки могут быть не в ядре? Тут всё сложно, на самом деле. Вообще-то не могут. Без поддержки ядра они работать не будут — в какой-то момент шедулер всё равно заберёт у нас процессор, и может отдать его другой нити нашего же процесса, если его никак не убедить в обратном, что требует поддержки ядра. Они могут быть инструментом оптимизации тяжёлых мьютексов.

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Works in
Date of birth
Registered
Activity