1
2
Fork
You've already forked spin
0

Documentation: Clarify guaranteed happens-before semantics for Once #158

Open
opened 2023年11月26日 23:14:54 +01:00 by briansmith · 1 comment
briansmith commented 2023年11月26日 23:14:54 +01:00 (Migrated from github.com)
Copy link

The implementation of Once provides acquire/release semantics but this is not promised anywhere in the documentation. I would like to submit a PR that provides this guarantee. In OnceCell, the issue was addressed in https://github.com/matklad/once_cell/pull/85/files by adding this to its documentation:

 /// Reading a non-`None` value out of `OnceCell` establishes a
 /// happens-before relationship with a corresponding write. For example, if
 /// thread A initializes the cell with `get_or_init(f)`, and thread B
 /// subsequently reads the result of this call, B also observes all the side
 /// effects of `f`.

I would like to add this guarantee to spin-rs's documentation too.

Notable, ring (https://github.com/briansmith/ring) has been depending on this for several years. See https://github.com/briansmith/ring/issues/931. Basically, ring uses a Once<()> to guard the initialization of a global variable (static mut) that is shared between Rust, C, and assembly language code, which all accesses it without any synchronization other than verifying that the Once<()> has been initialized.

In once.rs we have:

 let xchg = self.status.compare_exchange(
 Status::Incomplete,
 Status::Running,
 Ordering::Acquire,
 Ordering::Acquire,
 );

and then we have:

 // SAFETY: Release is required here, so that all memory accesses done in the
 // closure when initializing, become visible to other threads that perform Acquire
 // loads.
 self.status.store(Status::Complete, Ordering::Release);
The implementation of `Once` provides acquire/release semantics but this is not promised anywhere in the documentation. I would like to submit a PR that provides this guarantee. In OnceCell, the issue was addressed in https://github.com/matklad/once_cell/pull/85/files by adding this to its documentation: > ``` > /// Reading a non-`None` value out of `OnceCell` establishes a > /// happens-before relationship with a corresponding write. For example, if > /// thread A initializes the cell with `get_or_init(f)`, and thread B > /// subsequently reads the result of this call, B also observes all the side > /// effects of `f`. > ``` I would like to add this guarantee to spin-rs's documentation too. Notable, *ring* (https://github.com/briansmith/ring) has been depending on this for several years. See https://github.com/briansmith/ring/issues/931. Basically, *ring* uses a `Once<()>` to guard the initialization of a global variable (`static mut`) that is shared between Rust, C, and assembly language code, which all accesses it without any synchronization other than verifying that the `Once<()>` has been initialized. In once.rs we have: ``` let xchg = self.status.compare_exchange( Status::Incomplete, Status::Running, Ordering::Acquire, Ordering::Acquire, ); ``` and then we have: ``` // SAFETY: Release is required here, so that all memory accesses done in the // closure when initializing, become visible to other threads that perform Acquire // loads. self.status.store(Status::Complete, Ordering::Release); ````
zesterer commented 2023年11月27日 12:13:20 +01:00 (Migrated from github.com)
Copy link

I think this is a very reasonable thing to promise at the API level given the intended (and existing) uses of Once. I'd be happy to accept this.

I think this is a very reasonable thing to promise at the API level given the intended (and existing) uses of `Once`. I'd be happy to accept this.
Sign in to join this conversation.
No Branch/Tag specified
master
fixes
fix-ub
revert-127-ci
spinlock
No results found.
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
zesterer/spin#158
Reference in a new issue
zesterer/spin
No description provided.
Delete branch "%!s()"

Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?