Skip to content

Potential to modify ordering for compare_exhange in imp_std module #252

@wang384670111

Description

@wang384670111

I developed a static analysis tool to detect issues related to memory ordering, thread performance, and security. During my examination of several crates, I encountered alarms triggered by the following code:

once_cell/src/imp_std.rs

Lines 213 to 232 in c48d3c2

let node = Waiter {
thread: Cell::new(Some(thread::current())),
signaled: AtomicBool::new(false),
next: strict::map_addr(curr_queue, |q| q & !STATE_MASK),
};
let me = &node as *const Waiter as *mut Waiter;
let exchange = queue.compare_exchange(
curr_queue,
strict::map_addr(me, |q| q | curr_state),
Ordering::Release,
Ordering::Relaxed,
);
if let Err(new_queue) = exchange {
if strict::addr(new_queue) & STATE_MASK != curr_state {
return;
}
curr_queue = new_queue;
continue;
}

The meaning of the code should be that we need to have a successful initialization operation in Line222, but the compare exchange also entails reading the atomic pointer to the exchange. Therefore, it's necessary to use AcqRel and Acquire to observe any other modifications to the memory that the atomic pointer references, both when the compare exchange succeeds and when it fails.

I think compare exchange for queue uses AcqRel for the success case and Acquire for the fail case.

(happy to make a PR if this looks reasonable)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions