Rust Async Executor Memory Ordering Guarantees When Moving Tasks Across Threads?

Viewed 78

This is a rather basic question regarding the memory ordering guarantees inside the Rust async ecosystems. However, I don't seem to find a clear answer anywhere.

C++ memory ordering specifies the memory ordering from a thread-based perspective:

Release-Acquire ordering

If an atomic store in thread A is tagged memory_order_release and an atomic load in thread B from the same variable is tagged memory_order_acquire, all memory writes (non-atomic and relaxed atomic) that happened-before the atomic store from the point of view of thread A, become visible side-effects in thread B. That is, once the atomic load is completed, thread B is guaranteed to see everything thread A wrote to memory.

Various Rust async executors supports moving tasks across thread at .await points. A natural scenario would be:

  1. Task A was at Thread 1 and performed a Relaxed store at variable x.
  2. Task A hit a .await point
  3. Task A was moved to Thread 2 and awaked. And then performed a Release store at variable y.
  4. Task B was at Thread 3 and performed an Acquire load at variable y.

The question is: Is the Relaxed store from Thread 1 guaranteed to be visible in Task B after the Acquire load? E.g. if Task B at Thread 3 performed an Relaxed load at variable x afterwards, is it guaranteed that Task A's side effect will be visible?

This should depend on the implementation of synchronization mechanisms inside each async executor's task scheduler. Anyone familiar with them is appreciated.

1 Answers

Comment from Tokio maintainer:

When the task is moved from one thread to another, there is a synchronizes-with relation between the things before and after the .await. Depending on the exact circumstances, the synchronization comes from a mutex or an atomic using acquire & release semantics.

In C++ memory spec, synchronizse-with guarantees inter-thread happens-before. Therefore at least in Tokio, it should be safe to ignore memory ordering impact from a .await point.

Related