bytecodealliance / bytecodealliance/rustix

Expose raw-pointer futex wake/wait APIs instead of only &AtomicU32

Aperta
#1,603 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub
enhancement
Lingua principale
Rust
Stelle
2.1k
Fork
294
Merge medio
6g 22h
PR unite (30g)
4

Descrizione

`rustix::thread::futex::wake` currently requires a Rust reference:

```rust
#[inline]
pub fn wake(uaddr: &AtomicU32, flags: Flags, val: u32) -> io::Result {
// SAFETY: The raw pointers come from references or null.
unsafe { futex_val2(uaddr, Operation::Wake, flags, val, 0, ptr::null(), 0) }
}
```

This is too restrictive for some valid futex use cases.

The kernel futex interface fundamentally operates on an address. In some synchronization designs, the caller only has a raw pointer to the futex word, and creating an `&AtomicU32` is not justified by Rust’s reference rules.

A concrete example is a futex embedded in a node or frame owned by another thread, including stack allocation. The waking thread may only know the target futex address via a raw pointer stored in a queue. Once the waiter is woken, it may return immediately and destroy the node / stack frame before the waking function returns. In that situation, requiring `&AtomicU32` forces the caller to materialize a reference where only a raw-pointer contract is actually available.

Sketch:

```rust
struct Node {
state: AtomicU32,
next: AtomicPtr,
}

fn waiter_thread() {
let node = Node {
state: AtomicU32::new(0),
next: AtomicPtr::new(core::ptr::null_mut()),
};

enqueue(&node as *const Node);

unsafe {
// blocks while state == 0
futex_wait_raw(core::ptr::addr_of!(node.state), 0);
}

// after wake, this stack frame may exit immediately
}

fn waking_thread(node: *const Node) {
let futex_ptr = unsafe { core::ptr::addr_of!((*node).state) };

unsafe {
// This is the shape we need.
// Constructing `&AtomicU32` here is the problem.
futex_wake_raw(futex_ptr, Flags::PRIVATE, 1);
}
}
```

Today, libraries built on top of `rustix` end up needing to do one of these:

1. Manufacture `&AtomicU32` from a raw pointer even though they only truly have an address-based contract.
2. Avoid `rustix` for this case.
3. Carry extra ownership/borrowing structure that the kernel API does not require.

The problem is not that a raw-pointer API would be “safe”; it should be `unsafe`. The point is that the unsafety boundary should match the actual contract: “caller must provide a valid futex address for the duration of the syscall”, not “caller must already have a Rust reference”.

Proposed addition:

```rust
pub unsafe fn wake_ptr(
uaddr: *const AtomicU32,
flags: Flags,
val: u32,
) -> io::Result;
```

or perhaps

```rust
pub unsafe fn wake_ptr(
uaddr: NonNull,
flags: Flags,
val: u32,
) -> io::Result;
```

That would let higher-level synchronization code express the correct contract without fabricating references where only raw-pointer validity is available.

Guida per i contributori

Apri la guida per i contributori

Direzione di ricerca

Inizia con rustix::thread::futex::wake e la sua chiamata a futex_val2, quindi esamina le API futex circostanti e le relative convenzioni per la gestione dei puntatori. Determina l’API per raw pointer e il contratto di sicurezza adatti all’interfaccia esistente; il lavoro è completo quando viene esposta un’operazione wake unsafe basata sull’indirizzo senza richiedere un riferimento Rust fabbricato.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
linux, rust
Ambito
operating-systems
Tipo di issue
Funzionalità
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Tranquilla
Chiarezza
Abbastanza chiara
Idoneità per principianti
45/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.