mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 21:06:48 +00:00
Implement atomic wrapper for integer-like type
This commit is contained in:
parent
a7cb71161d
commit
21fedd1b60
44
Cargo.lock
generated
44
Cargo.lock
generated
@ -165,6 +165,7 @@ dependencies = [
|
||||
"aster-util",
|
||||
"aster-virtio",
|
||||
"atomic",
|
||||
"atomic-integer-wrapper",
|
||||
"bitflags 1.3.2",
|
||||
"bitvec",
|
||||
"bytemuck",
|
||||
@ -274,6 +275,15 @@ dependencies = [
|
||||
"bytemuck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic-integer-wrapper"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
@ -333,7 +343,7 @@ checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -488,7 +498,7 @@ dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -523,7 +533,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.77",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
@ -617,7 +627,7 @@ checksum = "ba330b70a5341d3bc730b8e205aaee97ddab5d9c448c4f51a7c2d924266fa8f9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -717,7 +727,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -996,7 +1006,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1101,7 +1111,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rand",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1182,9 +1192,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.78"
|
||||
version = "1.0.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
|
||||
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@ -1211,9 +1221,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.35"
|
||||
version = "1.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@ -1307,7 +1317,7 @@ checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1394,9 +1404,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.49"
|
||||
version = "2.0.77"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496"
|
||||
checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -1445,7 +1455,7 @@ checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1557,7 +1567,7 @@ checksum = "26a7b1c2c808c3db854a54d5215e3f7e7aaf5dcfbce095598cba6af29895695d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1755,5 +1765,5 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
@ -28,6 +28,7 @@ members = [
|
||||
"kernel/libs/keyable-arc",
|
||||
"kernel/libs/typeflags",
|
||||
"kernel/libs/typeflags-util",
|
||||
"kernel/libs/atomic-integer-wrapper",
|
||||
]
|
||||
exclude = [
|
||||
"kernel/libs/comp-sys/cargo-component",
|
||||
|
3
Makefile
3
Makefile
@ -110,7 +110,8 @@ NON_OSDK_CRATES := \
|
||||
kernel/libs/aster-rights-proc \
|
||||
kernel/libs/keyable-arc \
|
||||
kernel/libs/typeflags \
|
||||
kernel/libs/typeflags-util
|
||||
kernel/libs/typeflags-util \
|
||||
kernel/libs/atomic-integer-wrapper
|
||||
|
||||
# In contrast, OSDK crates depend on OSTD (or being `ostd` itself)
|
||||
# and need to be built or tested with OSDK.
|
||||
|
@ -23,6 +23,7 @@ typeflags-util = { path = "libs/typeflags-util" }
|
||||
aster-rights-proc = { path = "libs/aster-rights-proc" }
|
||||
aster-util = { path = "libs/aster-util" }
|
||||
aster-bigtcp = { path = "libs/aster-bigtcp" }
|
||||
atomic-integer-wrapper = { path = "libs/atomic-integer-wrapper" }
|
||||
id-alloc = { path = "../ostd/libs/id-alloc" }
|
||||
int-to-c-enum = { path = "libs/int-to-c-enum" }
|
||||
cpio-decoder = { path = "libs/cpio-decoder" }
|
||||
|
12
kernel/libs/atomic-integer-wrapper/Cargo.toml
Normal file
12
kernel/libs/atomic-integer-wrapper/Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "atomic-integer-wrapper"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "1.0.86"
|
||||
quote = "1.0.37"
|
||||
syn = { version = "2.0.77", features = ["full"] }
|
225
kernel/libs/atomic-integer-wrapper/src/lib.rs
Normal file
225
kernel/libs/atomic-integer-wrapper/src/lib.rs
Normal file
@ -0,0 +1,225 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
//! This crate provides a function-like macro for defining atomic version of integer-like type.
|
||||
//!
|
||||
//! By integer-like type we mean types that implement `Into<Integer>` and `From<Integer>/TryFrom<integer>`
|
||||
//! where `Integer` is a built-in integer type, e.g. u8.
|
||||
//!
|
||||
//! Below is a simple example. We define an atomic version `AtomicStatus` for integer-like
|
||||
//! type `Status`.
|
||||
//! ```ignore
|
||||
//! use atomic_integer_wrapper::define_atomic_version_of_integer_like_type;
|
||||
//! use core::sync::atomic::AtomicU8;
|
||||
//!
|
||||
//! #[repr(u8)]
|
||||
//! pub enum Status {
|
||||
//! Alive = 1,
|
||||
//! Dead = 0,
|
||||
//! }
|
||||
//!
|
||||
//! define_atomic_version_of_integer_like_type(Status, {
|
||||
//! #[derive(Debug)]
|
||||
//! pub struct AtomicStatus(AtomicU8);
|
||||
//! })
|
||||
//!
|
||||
//! impl From<u8> for Status {
|
||||
//! // ...
|
||||
//! }
|
||||
//!
|
||||
//! impl From<Status> for u8 {
|
||||
//! // ...
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! The `define_atomic_version_of_integer_like_type` macro will automatically implement
|
||||
//! `core::sync::atomic::AtomicU8`'s commonly used methods for `AtomicStatus` like `load` and `store`.
|
||||
//!
|
||||
//! The default behavior of the macro when converting a built-in integer to an integer-like type is to use
|
||||
//! implemented `From` trait for performance. If you'd like to enable some runtime checks that are implemented
|
||||
//! in `TryFrom` trait, you can specify the `try_from` boolean parameter. In the example above, it's like
|
||||
//! ```ignore
|
||||
//! define_atomic_version_of_integer_like_type(Status, try_from = true, {
|
||||
//! #[derive(Debug)]
|
||||
//! pub struct AtomicStatus(AtomicU8);
|
||||
//! })
|
||||
//! ```
|
||||
//!
|
||||
|
||||
#![feature(let_chains)]
|
||||
#![feature(proc_macro_diagnostic)]
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::Span;
|
||||
use quote::{quote, quote_spanned};
|
||||
use syn::{
|
||||
braced,
|
||||
parse::{Parse, ParseStream},
|
||||
parse_macro_input,
|
||||
spanned::Spanned,
|
||||
Error, Fields, Ident, ItemStruct, LitBool, Result, Token, Type,
|
||||
};
|
||||
|
||||
struct Input {
|
||||
integer_like_type: Type,
|
||||
try_from: LitBool,
|
||||
item: ItemStruct,
|
||||
}
|
||||
|
||||
impl Parse for Input {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let integer_like_type: Type = input.parse()?;
|
||||
input.parse::<Token![,]>()?;
|
||||
|
||||
let mut try_from = LitBool::new(false, Span::call_site());
|
||||
let lookahead = input.lookahead1();
|
||||
if lookahead.peek(Ident) {
|
||||
let key = input.parse::<Ident>()?;
|
||||
if key != "try_from" {
|
||||
return Err(Error::new(
|
||||
key.span(),
|
||||
format!(r#"Expected "try_from", found "{}""#, key),
|
||||
));
|
||||
}
|
||||
input.parse::<Token![=]>()?;
|
||||
try_from = input.parse()?;
|
||||
input.parse::<Token![,]>()?;
|
||||
}
|
||||
|
||||
let content;
|
||||
braced!(content in input);
|
||||
let item: ItemStruct = content.parse()?;
|
||||
|
||||
if !input.is_empty() {
|
||||
return Err(Error::new(Span::call_site(), "Unexpected token"));
|
||||
}
|
||||
|
||||
Ok(Input {
|
||||
integer_like_type,
|
||||
try_from,
|
||||
item,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn define_atomic_version_of_integer_like_type(input: TokenStream) -> TokenStream {
|
||||
let Input {
|
||||
integer_like_type,
|
||||
try_from,
|
||||
item,
|
||||
} = parse_macro_input!(input as Input);
|
||||
|
||||
let atomic_wrapper = item.ident.clone();
|
||||
let atomic_integer_type = if let Fields::Unnamed(ref fields_unnamed) = item.fields
|
||||
&& fields_unnamed.unnamed.len() == 1
|
||||
{
|
||||
fields_unnamed.unnamed.first().unwrap().ty.clone()
|
||||
} else {
|
||||
item.fields
|
||||
.span()
|
||||
.unwrap()
|
||||
.error("Expected a parenthesized struct like `struct AtomicFoo(AtomicU8)`")
|
||||
.emit();
|
||||
return TokenStream::new();
|
||||
};
|
||||
let from_integer = if try_from.value {
|
||||
quote_spanned! {integer_like_type.span()=>
|
||||
try_into().unwrap()
|
||||
}
|
||||
} else {
|
||||
quote_spanned! {integer_like_type.span()=>
|
||||
into()
|
||||
}
|
||||
};
|
||||
|
||||
let fn_new = quote! {
|
||||
pub fn new(value: impl Into<#integer_like_type>) -> Self {
|
||||
Self(<#atomic_integer_type>::new(value.into().into()))
|
||||
}
|
||||
};
|
||||
let fn_load = quote! {
|
||||
pub fn load(&self, order: core::sync::atomic::Ordering) -> #integer_like_type {
|
||||
self.0.load(order).#from_integer
|
||||
}
|
||||
};
|
||||
let fn_store = quote! {
|
||||
pub fn store(
|
||||
&self,
|
||||
val: impl Into<#integer_like_type>,
|
||||
order: core::sync::atomic::Ordering
|
||||
) {
|
||||
self.0.store(val.into().into(), order);
|
||||
}
|
||||
};
|
||||
let fn_swap = quote! {
|
||||
#[allow(dead_code)]
|
||||
pub fn swap(
|
||||
&self,
|
||||
val: impl Into<#integer_like_type>,
|
||||
order: core::sync::atomic::Ordering
|
||||
) -> #integer_like_type {
|
||||
self.0.swap(val.into().into(), order).#from_integer
|
||||
}
|
||||
};
|
||||
let fn_compare_exchange = quote! {
|
||||
#[allow(dead_code)]
|
||||
pub fn compare_exchange(
|
||||
&self,
|
||||
current: impl Into<#integer_like_type>,
|
||||
new: impl Into<#integer_like_type>,
|
||||
success: core::sync::atomic::Ordering,
|
||||
failure: core::sync::atomic::Ordering
|
||||
) -> core::result::Result<#integer_like_type, #integer_like_type> {
|
||||
self.0
|
||||
.compare_exchange(
|
||||
current.into().into(),
|
||||
new.into().into(),
|
||||
success,
|
||||
failure
|
||||
)
|
||||
.map(|val| val.#from_integer)
|
||||
.map_err(|val| val.#from_integer)
|
||||
}
|
||||
};
|
||||
let fn_fetch_update = quote! {
|
||||
#[allow(dead_code)]
|
||||
pub fn fetch_update<F>(
|
||||
&self,
|
||||
set_order: core::sync::atomic::Ordering,
|
||||
fetch_order: core::sync::atomic::Ordering,
|
||||
mut f: F
|
||||
) -> core::result::Result<#integer_like_type, #integer_like_type>
|
||||
where
|
||||
F: FnMut(#integer_like_type) -> Option<#integer_like_type>,
|
||||
{
|
||||
self.0
|
||||
.fetch_update(
|
||||
set_order,
|
||||
fetch_order,
|
||||
|old| f(old.#from_integer).map(<#integer_like_type>::into)
|
||||
)
|
||||
.map(|val| val.#from_integer)
|
||||
.map_err(|val| val.#from_integer)
|
||||
}
|
||||
};
|
||||
|
||||
let expanded = quote! {
|
||||
#item
|
||||
|
||||
impl #atomic_wrapper {
|
||||
#fn_new
|
||||
|
||||
#fn_load
|
||||
|
||||
#fn_store
|
||||
|
||||
#fn_swap
|
||||
|
||||
#fn_compare_exchange
|
||||
|
||||
#fn_fetch_update
|
||||
}
|
||||
};
|
||||
|
||||
TokenStream::from(expanded)
|
||||
}
|
@ -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(())
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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 => {
|
||||
|
@ -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::{
|
||||
|
@ -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::{
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
@ -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::*;
|
||||
|
@ -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 _))
|
||||
}
|
||||
|
@ -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 _))
|
||||
}
|
||||
|
@ -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 _))
|
||||
}
|
||||
|
@ -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 _))
|
||||
}
|
||||
|
@ -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 _
|
||||
))
|
||||
}
|
||||
|
@ -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 _
|
||||
))
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user