Skip to content

Commit

Permalink
Merge pull request #88 from elfenpiff/iox2-87-fix-issue-in-lock-free-…
Browse files Browse the repository at this point in the history
…queue

[#87] Fix undefined behavior in spsc {queue|index_queue}
  • Loading branch information
elfenpiff authored Jan 20, 2024
2 parents 5d91cc7 + 287cb16 commit ba45191
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 2 deletions.
1 change: 1 addition & 0 deletions doc/release-notes/iceoryx2-unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

* Fix `clock_nanosleep` on macOS [#80](https://github.com/eclipse-iceoryx/iceoryx2/issues/80)
* Fix broken `sighandler_t` translation [#81](https://github.com/eclipse-iceoryx/iceoryx2/issues/81)
* Fix undefined behavior in `spsc::{queue|index_queue}` [#87](https://github.com/eclipse-iceoryx/iceoryx2/issues/87)

### Refactoring

Expand Down
3 changes: 3 additions & 0 deletions iceoryx2-bb/lock-free/src/spsc/index_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,9 @@ pub mod details {
}

let value = unsafe { *self.at(read_position) };
// prevent that `out` and `read_position` statements are reordered according to
// the AS-IF rule.
core::sync::atomic::fence(Ordering::AcqRel);
self.read_position
.store(read_position + 1, Ordering::Relaxed);

Expand Down
5 changes: 4 additions & 1 deletion iceoryx2-bb/lock-free/src/spsc/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,11 @@ impl<T: Copy, const CAPACITY: usize> Queue<T, CAPACITY> {
.as_ptr()
};

// prevent that `out` and `read_position` statements are reordered according to
// the AS-IF rule.
core::sync::atomic::fence(Ordering::AcqRel);
self.read_position
.store(current_read_pos + 1, Ordering::Release);
.store(current_read_pos + 1, Ordering::Relaxed);

Some(out)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,12 @@ pub mod details {
/// * It has to be ensured that the memory is initialized with
/// [`SafelyOverflowingIndexQueue::init()`].
pub unsafe fn push(&self, value: usize) -> Option<usize> {
let write_position = self.write_position.load(Ordering::Relaxed);
////////////////
// SYNC POINT R
////////////////
// required when push in overflow case is called non-concurrently from a different
// thread
let write_position = self.write_position.load(Ordering::Acquire);
let read_position = self.read_position.load(Ordering::Relaxed);
let is_full = write_position == read_position + self.capacity;

Expand Down

0 comments on commit ba45191

Please sign in to comment.