Implement atomic wrapper for integer-like type

This commit is contained in:
jellllly420
2024-09-24 16:30:09 +08:00
committed by Tate, Hongliang Tian
parent a7cb71161d
commit 21fedd1b60
26 changed files with 437 additions and 241 deletions

View File

@ -93,7 +93,7 @@ impl Inode for Ext2Inode {
}
fn set_owner(&self, uid: Uid) -> Result<()> {
self.set_uid(uid.as_u32());
self.set_uid(uid.into());
Ok(())
}
@ -102,7 +102,7 @@ impl Inode for Ext2Inode {
}
fn set_group(&self, gid: Gid) -> Result<()> {
self.set_gid(gid.as_u32());
self.set_gid(gid.into());
Ok(())
}

View File

@ -1,8 +1,6 @@
// SPDX-License-Identifier: MPL-2.0
use core::sync::atomic::AtomicU32;
use atomic::Ordering;
use core::sync::atomic::{AtomicU32, Ordering};
use super::{
file_handle::FileLike,

View File

@ -6,6 +6,7 @@ use core::{
time::Duration,
};
use atomic_integer_wrapper::define_atomic_version_of_integer_like_type;
use ostd::sync::{PreemptDisabled, Waiter, Waker};
use super::sem_set::{SemSetInner, SEMVMX};
@ -46,22 +47,16 @@ pub enum Status {
Removed = 2,
}
struct AtomicStatus(AtomicU16);
impl AtomicStatus {
fn new(status: Status) -> Self {
Self(AtomicU16::new(status as u16))
}
fn status(&self) -> Status {
Status::try_from(self.0.load(Ordering::Relaxed)).unwrap()
}
fn set_status(&self, status: Status) {
self.0.store(status as u16, Ordering::Relaxed);
impl From<Status> for u16 {
fn from(value: Status) -> Self {
value as u16
}
}
define_atomic_version_of_integer_like_type!(Status, try_from = true, {
struct AtomicStatus(AtomicU16);
});
/// Pending atomic semop.
pub struct PendingOp {
sops: Vec<SemBuf>,
@ -76,7 +71,7 @@ impl PendingOp {
}
pub fn set_status(&self, status: Status) {
self.status.set_status(status);
self.status.store(status, Ordering::Relaxed);
}
pub fn waker(&self) -> &Option<Arc<Waker>> {
@ -92,7 +87,7 @@ impl Debug for PendingOp {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("PendingOp")
.field("sops", &self.sops)
.field("status", &(self.status.status()))
.field("status", &(self.status.load(Ordering::Relaxed)))
.field("pid", &self.pid)
.finish()
}
@ -205,7 +200,7 @@ pub fn sem_op(
drop(local_sem_sets);
waiter.wait();
match status.status() {
match status.load(Ordering::Relaxed) {
Status::Normal => Ok(()),
Status::Removed => Err(Error::new(Errno::EIDRM)),
Status::Pending => {

View File

@ -1,8 +1,7 @@
// SPDX-License-Identifier: MPL-2.0
use core::sync::atomic::AtomicBool;
use core::sync::atomic::{AtomicBool, Ordering};
use atomic::Ordering;
use takeable::Takeable;
use super::{

View File

@ -1,8 +1,6 @@
// SPDX-License-Identifier: MPL-2.0
use core::sync::atomic::AtomicBool;
use atomic::Ordering;
use core::sync::atomic::{AtomicBool, Ordering};
use super::{connected::Connected, connecting::Connecting, init::Init, listen::Listen};
use crate::{

View File

@ -2,6 +2,7 @@
use core::sync::atomic::{AtomicU64, Ordering};
use atomic_integer_wrapper::define_atomic_version_of_integer_like_type;
use bitflags::bitflags;
bitflags! {
@ -53,6 +54,8 @@ bitflags! {
}
impl CapSet {
const MASK: u64 = (1 << (CapSet::most_significant_bit() + 1)) - 1;
/// Converts the capability set to a `u32`. The higher bits are truncated.
pub fn as_u32(&self) -> u32 {
self.bits() as u32
@ -64,31 +67,37 @@ impl CapSet {
}
/// The most significant bit in a 64-bit `CapSet` that may be set to represent a Linux capability.
pub fn most_significant_bit() -> u8 {
pub const fn most_significant_bit() -> u8 {
// CHECKPOINT_RESTORE is the Linux capability with the largest numerical value
40
}
}
#[derive(Debug)]
pub(super) struct AtomicCapSet(AtomicU64);
impl TryFrom<u64> for CapSet {
type Error = &'static str;
impl AtomicCapSet {
pub const fn new(capset: CapSet) -> Self {
Self(AtomicU64::new(capset.bits))
}
pub fn set(&self, capset: CapSet) {
self.0.store(capset.bits(), Ordering::Relaxed);
}
pub fn get(&self) -> CapSet {
CapSet::from_bits_truncate(self.0.load(Ordering::Relaxed))
fn try_from(value: u64) -> Result<Self, Self::Error> {
if value & !CapSet::MASK != 0 {
Err("Invalid CapSet.")
} else {
Ok(CapSet { bits: value })
}
}
}
impl From<CapSet> for u64 {
fn from(value: CapSet) -> Self {
value.bits()
}
}
define_atomic_version_of_integer_like_type!(CapSet, try_from = true, {
#[derive(Debug)]
pub(super) struct AtomicCapSet(AtomicU64);
});
impl Clone for AtomicCapSet {
fn clone(&self) -> Self {
Self::new(self.get())
Self::new(self.load(Ordering::Relaxed))
}
}

View File

@ -1,5 +1,7 @@
// SPDX-License-Identifier: MPL-2.0
use core::sync::atomic::Ordering;
use ostd::sync::{RwLockReadGuard, RwLockWriteGuard};
use super::{group::AtomicGid, user::AtomicUid, Gid, Uid};
@ -75,28 +77,28 @@ impl Credentials_ {
// ******* Uid methods *******
pub(super) fn ruid(&self) -> Uid {
self.ruid.get()
self.ruid.load(Ordering::Relaxed)
}
pub(super) fn euid(&self) -> Uid {
self.euid.get()
self.euid.load(Ordering::Relaxed)
}
pub(super) fn suid(&self) -> Uid {
self.suid.get()
self.suid.load(Ordering::Relaxed)
}
pub(super) fn fsuid(&self) -> Uid {
self.fsuid.get()
self.fsuid.load(Ordering::Relaxed)
}
pub(super) fn set_uid(&self, uid: Uid) {
if self.is_privileged() {
self.ruid.set(uid);
self.euid.set(uid);
self.suid.set(uid);
self.ruid.store(uid, Ordering::Relaxed);
self.euid.store(uid, Ordering::Relaxed);
self.suid.store(uid, Ordering::Relaxed);
} else {
self.euid.set(uid);
self.euid.store(uid, Ordering::Relaxed);
}
}
@ -108,13 +110,13 @@ impl Credentials_ {
self.set_resuid_unchecked(ruid, euid, None);
if should_set_suid {
self.suid.set(self.euid());
self.suid.store(self.euid(), Ordering::Release);
}
// FIXME: should we set fsuid here? The linux document for syscall `setfsuid` is contradictory
// with the document of syscall `setreuid`. The `setfsuid` document says the `fsuid` is always
// the same as `euid`, but `setreuid` does not mention the `fsuid` should be set.
self.fsuid.set(self.euid());
self.fsuid.store(self.euid(), Ordering::Release);
Ok(())
}
@ -129,7 +131,7 @@ impl Credentials_ {
self.set_resuid_unchecked(ruid, euid, suid);
self.fsuid.set(self.euid());
self.fsuid.store(self.euid(), Ordering::Release);
Ok(())
}
@ -142,7 +144,7 @@ impl Credentials_ {
};
if self.is_privileged() {
self.fsuid.set(fsuid);
self.fsuid.store(fsuid, Ordering::Release);
return Ok(old_fsuid);
}
@ -153,17 +155,17 @@ impl Credentials_ {
)
}
self.fsuid.set(fsuid);
self.fsuid.store(fsuid, Ordering::Release);
Ok(old_fsuid)
}
pub(super) fn set_euid(&self, euid: Uid) {
self.euid.set(euid);
self.euid.store(euid, Ordering::Release);
}
pub(super) fn set_suid(&self, suid: Uid) {
self.suid.set(suid);
self.suid.store(suid, Ordering::Release);
}
// For `setreuid`, ruid can *NOT* be set to old suid,
@ -217,43 +219,43 @@ impl Credentials_ {
fn set_resuid_unchecked(&self, ruid: Option<Uid>, euid: Option<Uid>, suid: Option<Uid>) {
if let Some(ruid) = ruid {
self.ruid.set(ruid);
self.ruid.store(ruid, Ordering::Relaxed);
}
if let Some(euid) = euid {
self.euid.set(euid);
self.euid.store(euid, Ordering::Relaxed);
}
if let Some(suid) = suid {
self.suid.set(suid);
self.suid.store(suid, Ordering::Relaxed);
}
}
// ******* Gid methods *******
pub(super) fn rgid(&self) -> Gid {
self.rgid.get()
self.rgid.load(Ordering::Relaxed)
}
pub(super) fn egid(&self) -> Gid {
self.egid.get()
self.egid.load(Ordering::Relaxed)
}
pub(super) fn sgid(&self) -> Gid {
self.sgid.get()
self.sgid.load(Ordering::Relaxed)
}
pub(super) fn fsgid(&self) -> Gid {
self.fsgid.get()
self.fsgid.load(Ordering::Relaxed)
}
pub(super) fn set_gid(&self, gid: Gid) {
if self.is_privileged() {
self.rgid.set(gid);
self.egid.set(gid);
self.sgid.set(gid);
self.rgid.store(gid, Ordering::Relaxed);
self.egid.store(gid, Ordering::Relaxed);
self.sgid.store(gid, Ordering::Relaxed);
} else {
self.egid.set(gid);
self.egid.store(gid, Ordering::Relaxed);
}
}
@ -265,10 +267,10 @@ impl Credentials_ {
self.set_resgid_unchecked(rgid, egid, None);
if should_set_sgid {
self.sgid.set(self.egid());
self.sgid.store(self.egid(), Ordering::Relaxed);
}
self.fsgid.set(self.egid());
self.fsgid.store(self.egid(), Ordering::Relaxed);
Ok(())
}
@ -283,7 +285,7 @@ impl Credentials_ {
self.set_resgid_unchecked(rgid, egid, sgid);
self.fsgid.set(self.egid());
self.fsgid.store(self.egid(), Ordering::Relaxed);
Ok(())
}
@ -296,7 +298,7 @@ impl Credentials_ {
};
if self.is_privileged() {
self.fsgid.set(fsgid);
self.fsgid.store(fsgid, Ordering::Relaxed);
return Ok(old_fsgid);
}
@ -307,17 +309,17 @@ impl Credentials_ {
)
}
self.fsgid.set(fsgid);
self.fsgid.store(fsgid, Ordering::Relaxed);
Ok(old_fsgid)
}
pub(super) fn set_egid(&self, egid: Gid) {
self.egid.set(egid);
self.egid.store(egid, Ordering::Relaxed);
}
pub(super) fn set_sgid(&self, sgid: Gid) {
self.sgid.set(sgid);
self.sgid.store(sgid, Ordering::Relaxed);
}
// For `setregid`, rgid can *NOT* be set to old sgid,
@ -371,15 +373,15 @@ impl Credentials_ {
fn set_resgid_unchecked(&self, rgid: Option<Gid>, egid: Option<Gid>, sgid: Option<Gid>) {
if let Some(rgid) = rgid {
self.rgid.set(rgid);
self.rgid.store(rgid, Ordering::Relaxed);
}
if let Some(egid) = egid {
self.egid.set(egid);
self.egid.store(egid, Ordering::Relaxed);
}
if let Some(sgid) = sgid {
self.sgid.set(sgid);
self.sgid.store(sgid, Ordering::Relaxed);
}
}
@ -396,27 +398,30 @@ impl Credentials_ {
// ******* Linux Capability methods *******
pub(super) fn inheritable_capset(&self) -> CapSet {
self.inheritable_capset.get()
self.inheritable_capset.load(Ordering::Relaxed)
}
pub(super) fn permitted_capset(&self) -> CapSet {
self.permitted_capset.get()
self.permitted_capset.load(Ordering::Relaxed)
}
pub(super) fn effective_capset(&self) -> CapSet {
self.effective_capset.get()
self.effective_capset.load(Ordering::Relaxed)
}
pub(super) fn set_inheritable_capset(&self, inheritable_capset: CapSet) {
self.inheritable_capset.set(inheritable_capset);
self.inheritable_capset
.store(inheritable_capset, Ordering::Relaxed);
}
pub(super) fn set_permitted_capset(&self, permitted_capset: CapSet) {
self.permitted_capset.set(permitted_capset);
self.permitted_capset
.store(permitted_capset, Ordering::Relaxed);
}
pub(super) fn set_effective_capset(&self, effective_capset: CapSet) {
self.effective_capset.set(effective_capset);
self.effective_capset
.store(effective_capset, Ordering::Relaxed);
}
}

View File

@ -2,6 +2,8 @@
use core::sync::atomic::{AtomicU32, Ordering};
use atomic_integer_wrapper::define_atomic_version_of_integer_like_type;
use crate::prelude::*;
#[derive(Debug, Clone, Copy, Pod, Default, PartialEq, Eq, PartialOrd, Ord)]
@ -17,10 +19,6 @@ impl Gid {
Self(ROOT_GID)
}
pub const fn as_u32(&self) -> u32 {
self.0
}
pub const fn is_root(&self) -> bool {
self.0 == ROOT_GID
}
@ -28,25 +26,25 @@ impl Gid {
const ROOT_GID: u32 = 0;
#[derive(Debug)]
pub(super) struct AtomicGid(AtomicU32);
impl AtomicGid {
pub const fn new(gid: Gid) -> Self {
Self(AtomicU32::new(gid.as_u32()))
}
pub fn set(&self, gid: Gid) {
self.0.store(gid.as_u32(), Ordering::Relaxed)
}
pub fn get(&self) -> Gid {
Gid(self.0.load(Ordering::Relaxed))
impl From<u32> for Gid {
fn from(value: u32) -> Self {
Self::new(value)
}
}
impl From<Gid> for u32 {
fn from(value: Gid) -> Self {
value.0
}
}
define_atomic_version_of_integer_like_type!(Gid, {
#[derive(Debug)]
pub(super) struct AtomicGid(AtomicU32);
});
impl Clone for AtomicGid {
fn clone(&self) -> Self {
Self(AtomicU32::new(self.0.load(Ordering::Relaxed)))
Self::new(self.load(Ordering::Relaxed))
}
}

View File

@ -2,6 +2,8 @@
use core::sync::atomic::{AtomicU32, Ordering};
use atomic_integer_wrapper::define_atomic_version_of_integer_like_type;
use crate::prelude::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Pod)]
@ -22,35 +24,33 @@ impl Uid {
pub const fn is_root(&self) -> bool {
self.0 == ROOT_UID
}
}
pub const fn as_u32(&self) -> u32 {
self.0
impl From<u32> for Uid {
fn from(value: u32) -> Self {
Self::new(value)
}
}
#[derive(Debug)]
pub(super) struct AtomicUid(AtomicU32);
impl From<Uid> for u32 {
fn from(value: Uid) -> Self {
value.0
}
}
define_atomic_version_of_integer_like_type!(Uid, {
#[derive(Debug)]
pub(super) struct AtomicUid(AtomicU32);
});
impl AtomicUid {
pub const fn new(uid: Uid) -> Self {
Self(AtomicU32::new(uid.as_u32()))
}
pub fn set(&self, uid: Uid) {
self.0.store(uid.as_u32(), Ordering::Release)
}
pub fn get(&self) -> Uid {
Uid(self.0.load(Ordering::Acquire))
}
pub fn is_root(&self) -> bool {
self.get().is_root()
self.load(Ordering::Acquire).is_root()
}
}
impl Clone for AtomicUid {
fn clone(&self) -> Self {
Self(AtomicU32::new(self.0.load(Ordering::Acquire)))
Self::new(self.load(Ordering::Acquire))
}
}

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MPL-2.0
use core::sync::atomic::Ordering;
use core::sync::atomic::{AtomicU32, Ordering};
use self::timer_manager::PosixTimerManager;
use super::{
@ -35,6 +35,7 @@ mod timer_manager;
use aster_rights::Full;
use atomic::Atomic;
use atomic_integer_wrapper::define_atomic_version_of_integer_like_type;
pub use builder::ProcessBuilder;
pub use job_control::JobControl;
use ostd::{sync::WaitQueue, task::Task};
@ -44,6 +45,10 @@ pub use terminal::Terminal;
/// Process id.
pub type Pid = u32;
define_atomic_version_of_integer_like_type!(Pid, {
#[derive(Debug)]
pub struct AtomicPid(AtomicU32);
});
/// Process group id.
pub type Pgid = u32;
/// Session Id.
@ -107,11 +112,11 @@ pub struct Process {
///
/// This type caches the value of the PID so that it can be retrieved cheaply.
///
/// The benefit of using `ParentProcess` over `(Mutex<Weak<Process>>, Atomic<Pid>,)` is to
/// The benefit of using `ParentProcess` over `(Mutex<Weak<Process>>, AtomicPid,)` is to
/// enforce the invariant that the cached PID and the weak reference are always kept in sync.
pub struct ParentProcess {
process: Mutex<Weak<Process>>,
pid: Atomic<Pid>,
pid: AtomicPid,
}
impl ParentProcess {
@ -123,7 +128,7 @@ impl ParentProcess {
Self {
process: Mutex::new(process),
pid: Atomic::new(pid),
pid: AtomicPid::new(pid),
}
}

View File

@ -12,6 +12,8 @@ use core::{
sync::atomic::{AtomicU64, Ordering},
};
use atomic_integer_wrapper::define_atomic_version_of_integer_like_type;
use super::{constants::MIN_STD_SIG_NUM, sig_num::SigNum};
use crate::prelude::*;
@ -158,68 +160,26 @@ impl LowerHex for SigSet {
/// [`Relaxed`]: core::sync::atomic::Ordering::Relaxed
pub type AtomicSigMask = AtomicSigSet;
/// An atomic signal set.
pub struct AtomicSigSet(AtomicU64);
define_atomic_version_of_integer_like_type!(SigSet, {
pub struct AtomicSigSet(AtomicU64);
});
impl From<SigSet> for AtomicSigSet {
fn from(set: SigSet) -> Self {
AtomicSigSet(AtomicU64::new(set.bits))
Self::new(set)
}
}
impl AtomicSigSet {
pub fn new_empty() -> Self {
AtomicSigSet(AtomicU64::new(0))
AtomicSigSet::new(0)
}
pub fn new_full() -> Self {
AtomicSigSet(AtomicU64::new(!0))
}
pub fn load(&self, ordering: Ordering) -> SigSet {
SigSet {
bits: self.0.load(ordering),
}
}
pub fn store(&self, new_mask: impl Into<SigMask>, ordering: Ordering) {
self.0.store(new_mask.into().bits, ordering);
}
pub fn swap(&self, new_mask: impl Into<SigMask>, ordering: Ordering) -> SigSet {
let bits = self.0.swap(new_mask.into().bits, ordering);
SigSet { bits }
AtomicSigSet::new(!0)
}
pub fn contains(&self, signals: impl Into<SigSet>, ordering: Ordering) -> bool {
SigSet {
bits: self.0.load(ordering),
}
.contains(signals.into())
}
/// Applies an update to the signal set.
///
/// This is the same as [`AtomicU64::fetch_update`], but the closure `f`
/// operates on a [`SigMask`] instead of a `u64`.
///
/// It would be a bit slow since it would check if the value is written by
/// another thread while evaluating the closure `f`. If you are confident
/// that there's no such race, don't use this method.
pub fn fetch_update<F>(
&self,
set_order: Ordering,
fetch_order: Ordering,
mut f: F,
) -> core::result::Result<SigMask, SigMask>
where
F: FnMut(SigMask) -> Option<SigMask>,
{
self.0
.fetch_update(set_order, fetch_order, |bits| {
f(SigMask { bits }).map(|set| set.bits)
})
.map(SigMask::from)
.map_err(SigMask::from)
self.load(ordering).contains(signals.into())
}
}

View File

@ -2,9 +2,7 @@
#![allow(dead_code)]
use core::sync::atomic::AtomicU8;
use atomic::Ordering;
use core::sync::atomic::{AtomicU8, Ordering};
use super::constants::*;
use crate::prelude::*;

View File

@ -1,10 +1,10 @@
// SPDX-License-Identifier: MPL-2.0
use super::SyscallReturn;
use crate::prelude::*;
use crate::{prelude::*, process::Gid};
pub fn sys_getegid(ctx: &Context) -> Result<SyscallReturn> {
let egid = ctx.posix_thread.credentials().egid();
Ok(SyscallReturn::Return(egid.as_u32() as _))
Ok(SyscallReturn::Return(<Gid as Into<u32>>::into(egid) as _))
}

View File

@ -1,10 +1,10 @@
// SPDX-License-Identifier: MPL-2.0
use super::SyscallReturn;
use crate::prelude::*;
use crate::{prelude::*, process::Uid};
pub fn sys_geteuid(ctx: &Context) -> Result<SyscallReturn> {
let euid = ctx.posix_thread.credentials().euid();
Ok(SyscallReturn::Return(euid.as_u32() as _))
Ok(SyscallReturn::Return(<Uid as Into<u32>>::into(euid) as _))
}

View File

@ -1,10 +1,10 @@
// SPDX-License-Identifier: MPL-2.0
use super::SyscallReturn;
use crate::prelude::*;
use crate::{prelude::*, process::Gid};
pub fn sys_getgid(ctx: &Context) -> Result<SyscallReturn> {
let gid = ctx.posix_thread.credentials().rgid();
Ok(SyscallReturn::Return(gid.as_u32() as _))
Ok(SyscallReturn::Return(<Gid as Into<u32>>::into(gid) as _))
}

View File

@ -1,10 +1,10 @@
// SPDX-License-Identifier: MPL-2.0
use super::SyscallReturn;
use crate::prelude::*;
use crate::{prelude::*, process::Uid};
pub fn sys_getuid(ctx: &Context) -> Result<SyscallReturn> {
let uid = ctx.posix_thread.credentials().ruid();
Ok(SyscallReturn::Return(uid.as_u32() as _))
Ok(SyscallReturn::Return(<Uid as Into<u32>>::into(uid) as _))
}

View File

@ -17,5 +17,7 @@ pub fn sys_setfsgid(gid: i32, ctx: &Context) -> Result<SyscallReturn> {
credentials.set_fsgid(fsgid)?
};
Ok(SyscallReturn::Return(old_fsgid.as_u32() as _))
Ok(SyscallReturn::Return(
<Gid as Into<u32>>::into(old_fsgid) as _
))
}

View File

@ -17,5 +17,7 @@ pub fn sys_setfsuid(uid: i32, ctx: &Context) -> Result<SyscallReturn> {
credentials.set_fsuid(fsuid)?
};
Ok(SyscallReturn::Return(old_fsuid.as_u32() as _))
Ok(SyscallReturn::Return(
<Uid as Into<u32>>::into(old_fsuid) as _
))
}

View File

@ -121,8 +121,8 @@ impl From<Metadata> for Stat {
st_ino: info.ino,
st_nlink: info.nlinks,
st_mode: info.type_ as u32 | info.mode.bits() as u32,
st_uid: info.uid.as_u32(),
st_gid: info.gid.as_u32(),
st_uid: info.uid.into(),
st_gid: info.gid.into(),
__pad0: 0,
st_rdev: info.rdev,
st_size: info.size as isize,

View File

@ -1,43 +1,14 @@
// SPDX-License-Identifier: MPL-2.0
use core::sync::atomic::{AtomicU8, Ordering};
use core::sync::atomic::AtomicU8;
use atomic_integer_wrapper::define_atomic_version_of_integer_like_type;
use int_to_c_enum::TryFromInt;
/// A `ThreadStatus` which can be safely shared between threads.
#[derive(Debug)]
pub struct AtomicThreadStatus(AtomicU8);
impl AtomicThreadStatus {
/// Creates a new atomic status.
pub fn new(status: ThreadStatus) -> Self {
Self(AtomicU8::new(status as u8))
}
/// Loads a value from the atomic status.
pub fn load(&self, order: Ordering) -> ThreadStatus {
ThreadStatus::try_from(self.0.load(order)).unwrap()
}
/// Stores a value into the atomic status.
pub fn store(&self, new_status: ThreadStatus, order: Ordering) {
self.0.store(new_status as u8, order);
}
/// Stores a value into the atomic status if the current value is the same as the `current` value.
pub fn compare_exchange(
&self,
current: ThreadStatus,
new: ThreadStatus,
success: Ordering,
failure: Ordering,
) -> Result<ThreadStatus, ThreadStatus> {
self.0
.compare_exchange(current as u8, new as u8, success, failure)
.map(|val| ThreadStatus::try_from(val).unwrap())
.map_err(|val| ThreadStatus::try_from(val).unwrap())
}
}
define_atomic_version_of_integer_like_type!(ThreadStatus, try_from = true, {
#[derive(Debug)]
pub struct AtomicThreadStatus(AtomicU8);
});
#[derive(Clone, Copy, PartialEq, Eq, Debug, TryFromInt)]
#[repr(u8)]
@ -61,3 +32,9 @@ impl ThreadStatus {
*self == ThreadStatus::Stopped
}
}
impl From<ThreadStatus> for u8 {
fn from(value: ThreadStatus) -> Self {
value as u8
}
}