172 похожих чатов

Всем привет! Вопрос по мемори ордерингам. Есть 2 треда, на

втором работает tokio с асинк циклом. В конце работы - первый тред ставит флаг exit и вызывает wake, чтобы футура во втором треде проснулась:
self.exit.store(true, Ordering::Relaxed);
self.waker.lock().unwrap().wake();
Во втором треде при получении wake() футура успешно завершается, после чего проверяется флаг exit и происходит выход:
pending_future.await; // гарантировано ожидаем wake тут
if self.exit.load(Ordering::Relaxed) {
return;
}
Вопрос вот в чем. exit - атомарный булиан, никаких операций кроме единичной записи перед wake() и чтения во втором треде после wake() нет. Возможна ли следующая последовательность исполнения на x86-64 или arm64 с relaxed мемори ордерингом?:
thread1: wake() - thread2: awaken - thread2:reads exit false - thread1: writes exit true

6 ответов

10 просмотров
⁣Денис-Давыдов Автор вопроса

Как бы с одной стороны модификейшн ордер для exit: false, true и ничто не мешает второму треду получить из кэша false. Но с другой стороны в первом треде все-таки запись происходит до wake, а wake еще и под мьютексом - не вызовет ли что-то там все-таки какую-то синхронизацию кэшей?

⁣Денис-Давыдов Автор вопроса
⁣Денис Давыдов
Как бы с одной стороны модификейшн ордер для exit:...

Похоже да, wake() у себя внутри вызывает compare_exchange c AcqRel, который обещает что все записи в память от треда 1 до этого будут видны треду 2. Точно ли я ничего не путаю?

А через что ты будишь токио тред?

⁣Денис-Давыдов Автор вопроса
Nano
А через что ты будишь токио тред?

Просто waker из контекста. impl Future for PendingFuture { type Output = (); fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { let me = self.get_mut(); // ... тут проверки не готова ли футура me.waker.lock().replace(cx.waker().clone()); Poll::Pending } }

⁣Денис-Давыдов Автор вопроса
Nano
А через что ты будишь токио тред?

Собственно проверил loomом: #[cfg(test)] mod atomic_tests { use loom::sync::atomic::AtomicBool; use loom::sync::atomic::Ordering; use loom::thread; use loom::thread::yield_now; #[test] fn test_sync() { loom::model(|| { let exit: &'static _ = Box::leak(Box::new(AtomicBool::new(false))); let wake: &'static _ = Box::leak(Box::new(AtomicBool::new(false))); let b= thread::spawn(move || { while !wake.load(Ordering::Acquire) { yield_now(); }; assert!(exit.load(Ordering::Relaxed)); }); exit.store(true, Ordering::Relaxed); // wake() в tokio под капотом: // https://github.com/tokio-rs/tokio/blob/master/tokio/src/runtime/task/state.rs#L215 // https://github.com/tokio-rs/tokio/blob/master/tokio/src/runtime/task/state.rs#L467 assert!(wake.compare_exchange(false, true, Ordering::AcqRel, Ordering::Acquire).is_ok()); b.join().unwrap(); }) } }

⁣Денис Давыдов
Похоже да, wake() у себя внутри вызывает compare_e...

Должно. Если глянуть в реализацию мьютексов, там там данные которые он охраняет даже не в атомике лежат и работает)

Похожие вопросы

Обсуждают сегодня

что насчет пагинга? на осдеве непонятно(
Vi Chapmann 🪙
26
А как старый хаскел с новым стыковать ? потому как тут работает https://play.haskell.org/saved/C3xpMzcd, а вот тут https://stepik.org/lesson/7602/step/9?unit=1473 нет ошибка C...
Fedor
131
Вопрос я правильно понимаю что в коде newtype ArrowMap k v = ArrowMap { getArrowMap :: k -> Maybe v } getArrowMap есть функция типа k -> Maybe v, если да, то не понимаю задач...
Fedor
64
Ребят, что лучше для реверса: гидра или ида?
En Vind Av Sorg
26
Делаю велосипед логгер. К сообщению хочу прикрутить некоторую информацию, типа, кем отправлено, какой уровень, и всякое такое. И тут подумалось мне, почему бы не хранить весь...
Serjone
24
Как Вы считаете нормально ли в двадцатых годах 21 века в ВУЗах Российской Федерации обучать студентов работе с TASM? Не слишком ли это "архаично"? (Если оффтоп или флейм для э...
Spiker01
52
если загрузчик efi? если сама PML4 PDPT PDT PT лежит в неудобном для меня месте?
Vi Chapmann 🪙
8
Комрады, хотел уточнить. Проперть в OnDestroy юнита-хозяина по-прежнему доступна? И еще уточнение: finalization юнита наступает раньше или позже OnDestroy?
Ed Doc
48
А я же правильно понимаю, что инструкция AT в ld только сохраняет метаинформации о том, куда загрузить сегмент, которую далее из эльфика читает grub(ну если граб)? Но я тогда ...
Evg Resh
2
Господа, импользую кастомный загрузчик, ядро запускается сразу в длинном режиме, хочу узнать, сколько всего физической ОЗУ есть у машины. И, может, знаете какие-то подводные к...
Vi Chapmann 🪙
6
Карта сайта