Skip to content

Commit

Permalink
[eclipse-iceoryx#200] Add IceAtomic to support AtomicU64 on 32-bit
Browse files Browse the repository at this point in the history
  • Loading branch information
elfenpiff committed Apr 29, 2024
1 parent e71c5a4 commit f21dda9
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 5 deletions.
144 changes: 144 additions & 0 deletions iceoryx2-pal/concurrency-sync/src/atomic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// Copyright (c) 2024 Contributors to the Eclipse Foundation
//
// See the NOTICE file(s) distributed with this work for additional
// information regarding copyright ownership.
//
// This program and the accompanying materials are made available under the
// terms of the Apache Software License 2.0 which is available at
// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license
// which is available at https://opensource.org/licenses/MIT.
//
// SPDX-License-Identifier: Apache-2.0 OR MIT

use core::{
cell::UnsafeCell,
ops::{AddAssign, SubAssign},
sync::atomic::Ordering,
};

use crate::{rwlock::RwLockWriterPreference, WaitAction};

pub type IceAtomicBool = core::sync::atomic::AtomicBool;
pub type IceAtomicUsize = core::sync::atomic::AtomicUsize;

pub type IceAtomicU8 = core::sync::atomic::AtomicU8;
pub type IceAtomicU16 = core::sync::atomic::AtomicU16;
pub type IceAtomicU32 = core::sync::atomic::AtomicU32;
pub type IceAtomicI8 = core::sync::atomic::AtomicI8;
pub type IceAtomicI16 = core::sync::atomic::AtomicI16;
pub type IceAtomicI32 = core::sync::atomic::AtomicI32;

#[cfg(target_pointer_width = "64")]
pub type IceAtomicI64 = core::sync::atomic::AtomicI64;

#[cfg(target_pointer_width = "64")]
pub type IceAtomicU64 = core::sync::atomic::AtomicU64;

#[cfg(target_pointer_width = "32")]
pub type IceAtomicI64 = IceAtomic<i64>;

#[cfg(target_pointer_width = "32")]
pub type IceAtomicU64 = IceAtomic<u64>;

type LockType = RwLockWriterPreference;

#[repr(C)]
pub struct IceAtomic<T: Copy + Send> {
data: UnsafeCell<T>,
lock: LockType,
}

impl<T: Copy + Send + Eq + AddAssign + SubAssign> IceAtomic<T> {
pub fn new(v: T) -> Self {
Self {
data: UnsafeCell::new(v),
lock: LockType::new(),
}
}

fn read_lock(&self) {
self.lock.read_lock(|_, _| WaitAction::Continue);
}

fn write_lock(&self) {
self.lock
.write_lock(|_, _| WaitAction::Continue, |_| {}, |_| {});
}

fn unlock(&self) {
self.lock.unlock(|_| {}, |_| {});
}

pub fn compare_exchange(
&self,
current: T,
new: T,
success: Ordering,
failure: Ordering,
) -> Result<T, T> {
self.write_lock();
let data = unsafe { *self.data.get() };
if data != current {
core::sync::atomic::fence(failure);
self.unlock();
return Err(data);
}

unsafe { *self.data.get() = new };
core::sync::atomic::fence(success);
self.unlock();
Ok(data)
}

pub fn compare_exchange_weak(
&self,
current: T,
new: T,
success: Ordering,
failure: Ordering,
) -> Result<T, T> {
self.compare_exchange(current, new, success, failure)
}

pub fn fetch_add(&self, value: T, order: Ordering) -> T {
self.write_lock();
let data = unsafe { *self.data.get() };
unsafe { *self.data.get() += value };
core::sync::atomic::fence(order);
self.unlock();
data
}

pub fn fetch_sub(&self, value: T, order: Ordering) -> T {
self.write_lock();
let data = unsafe { *self.data.get() };
unsafe { *self.data.get() -= value };
core::sync::atomic::fence(order);
self.unlock();
data
}

pub fn load(&self, order: Ordering) -> T {
self.read_lock();
let data = unsafe { *self.data.get() };
core::sync::atomic::fence(order);
self.unlock();
data
}

pub fn store(&self, value: T, order: Ordering) {
self.write_lock();
unsafe { *self.data.get() = value };
core::sync::atomic::fence(order);
self.unlock();
}

pub fn swap(&self, value: T, order: Ordering) -> T {
self.write_lock();
let data = unsafe { *self.data.get() };
unsafe { *self.data.get() = value };
core::sync::atomic::fence(order);
self.unlock();
data
}
}
1 change: 1 addition & 0 deletions iceoryx2-pal/concurrency-sync/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

const SPIN_REPETITIONS: u64 = 10000;

pub mod atomic;
pub mod barrier;
pub mod condition_variable;
pub mod mutex;
Expand Down
10 changes: 5 additions & 5 deletions iceoryx2-pal/concurrency-sync/src/rwlock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ pub struct RwLockReaderPreference {

impl Default for RwLockReaderPreference {
fn default() -> Self {
Self {
reader_count: AtomicU32::new(UNLOCKED),
}
Self::new()
}
}

impl RwLockReaderPreference {
pub fn new() -> Self {
Self::default()
pub const fn new() -> Self {
Self {
reader_count: AtomicU32::new(UNLOCKED),
}
}

pub fn try_read_lock(&self) -> WaitResult {
Expand Down

0 comments on commit f21dda9

Please sign in to comment.