Module cros_async::sys::unix::uring_executor
source · Expand description
UringReactor
Read/Write buffer management.
There are two key issues managing asynchronous IO buffers in rust.
- The kernel has a mutable reference to the memory until the completion is returned. Rust must not have any references to it during that time.
- The memory must remain valid as long as the kernel has a reference to it.
The kernel’s mutable borrow of the buffer
Because the buffers used for read and write must be passed to the kernel for an unknown
duration, the functions must maintain ownership of the memory. The core of this problem is that
the lifetime of the future isn’t tied to the scope in which the kernel can modify the buffer the
future has a reference to. The buffer can be modified at any point from submission until the
operation completes. The operation can’t be synchronously canceled when the future is dropped,
and Drop can’t be used for safety guarantees. To ensure this never happens, only memory that
implements BackingMemory
is accepted. For implementors of BackingMemory
the mut borrow
isn’t an issue because those are already Ok with external modifications to the memory (Like a
VolatileSlice
).
Buffer lifetime
What if the kernel’s reference to the buffer outlives the buffer itself? This could happen if a read operation was submitted, then the memory is dropped. To solve this, the executor takes an Arc to the backing memory. Vecs being read to are also wrapped in an Arc before being passed to the executor. The executor holds the Arc and ensures all operations are complete before dropping it, that guarantees the memory is valid for the duration.
The buffers have to be on the heap. Because we don’t have a way to cancel a future if it is dropped(can’t rely on drop running), there is no way to ensure the kernel’s buffer remains valid until the operation completes unless the executor holds an Arc to the memory on the heap.
Using Vec
for reads/writes.
There is a convenience wrapper VecIoWrapper
provided for fully owned vectors. This type
ensures that only the kernel is allowed to access the Vec
and wraps the the Vec
in an Arc to
ensure it lives long enough.