mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-16 17:46:48 +00:00
Refactor RLimit64 to atomic
This commit is contained in:
parent
96d83e43b4
commit
eca3c8fb59
@ -82,7 +82,7 @@ pub struct Process {
|
|||||||
/// Process group
|
/// Process group
|
||||||
pub(super) process_group: Mutex<Weak<ProcessGroup>>,
|
pub(super) process_group: Mutex<Weak<ProcessGroup>>,
|
||||||
/// resource limits
|
/// resource limits
|
||||||
resource_limits: Mutex<ResourceLimits>,
|
resource_limits: ResourceLimits,
|
||||||
/// Scheduling priority nice value
|
/// Scheduling priority nice value
|
||||||
/// According to POSIX.1, the nice value is a per-process attribute,
|
/// According to POSIX.1, the nice value is a per-process attribute,
|
||||||
/// the threads in a process should share a nice value.
|
/// the threads in a process should share a nice value.
|
||||||
@ -217,7 +217,7 @@ impl Process {
|
|||||||
sig_dispositions,
|
sig_dispositions,
|
||||||
parent_death_signal: AtomicSigNum::new_empty(),
|
parent_death_signal: AtomicSigNum::new_empty(),
|
||||||
exit_signal: AtomicSigNum::new_empty(),
|
exit_signal: AtomicSigNum::new_empty(),
|
||||||
resource_limits: Mutex::new(resource_limits),
|
resource_limits,
|
||||||
nice: AtomicNice::new(nice),
|
nice: AtomicNice::new(nice),
|
||||||
timer_manager: PosixTimerManager::new(&prof_clock, process_ref),
|
timer_manager: PosixTimerManager::new(&prof_clock, process_ref),
|
||||||
prof_clock,
|
prof_clock,
|
||||||
@ -320,7 +320,7 @@ impl Process {
|
|||||||
*self.executable_path.write() = executable_path;
|
*self.executable_path.write() = executable_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resource_limits(&self) -> &Mutex<ResourceLimits> {
|
pub fn resource_limits(&self) -> &ResourceLimits {
|
||||||
&self.resource_limits
|
&self.resource_limits
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,11 @@
|
|||||||
|
|
||||||
#![expect(non_camel_case_types)]
|
#![expect(non_camel_case_types)]
|
||||||
|
|
||||||
|
use core::{
|
||||||
|
array,
|
||||||
|
sync::atomic::{AtomicU64, Ordering},
|
||||||
|
};
|
||||||
|
|
||||||
use super::process_vm::{INIT_STACK_SIZE, USER_HEAP_SIZE_LIMIT};
|
use super::process_vm::{INIT_STACK_SIZE, USER_HEAP_SIZE_LIMIT};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
@ -30,43 +35,44 @@ impl ResourceLimits {
|
|||||||
pub fn get_rlimit(&self, resource: ResourceType) -> &RLimit64 {
|
pub fn get_rlimit(&self, resource: ResourceType) -> &RLimit64 {
|
||||||
&self.rlimits[resource as usize]
|
&self.rlimits[resource as usize]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a mutable reference to a specific resource limit
|
|
||||||
pub fn get_rlimit_mut(&mut self, resource: ResourceType) -> &mut RLimit64 {
|
|
||||||
&mut self.rlimits[resource as usize]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ResourceLimits {
|
impl Default for ResourceLimits {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let mut rlimits = [RLimit64::default(); RLIMIT_COUNT];
|
let mut rlimits: [RLimit64; RLIMIT_COUNT] = array::from_fn(|_| RLimit64::default());
|
||||||
|
|
||||||
// Setting the resource limits with predefined values
|
// Setting the resource limits with predefined values
|
||||||
rlimits[ResourceType::RLIMIT_CPU as usize] = RLimit64::new(RLIM_INFINITY, RLIM_INFINITY);
|
rlimits[ResourceType::RLIMIT_CPU as usize] =
|
||||||
rlimits[ResourceType::RLIMIT_FSIZE as usize] = RLimit64::new(RLIM_INFINITY, RLIM_INFINITY);
|
RLimit64::new(RLIM_INFINITY, RLIM_INFINITY).unwrap();
|
||||||
|
rlimits[ResourceType::RLIMIT_FSIZE as usize] =
|
||||||
|
RLimit64::new(RLIM_INFINITY, RLIM_INFINITY).unwrap();
|
||||||
rlimits[ResourceType::RLIMIT_DATA as usize] =
|
rlimits[ResourceType::RLIMIT_DATA as usize] =
|
||||||
RLimit64::new(USER_HEAP_SIZE_LIMIT as u64, RLIM_INFINITY);
|
RLimit64::new(USER_HEAP_SIZE_LIMIT as u64, RLIM_INFINITY).unwrap();
|
||||||
rlimits[ResourceType::RLIMIT_STACK as usize] =
|
rlimits[ResourceType::RLIMIT_STACK as usize] =
|
||||||
RLimit64::new(INIT_STACK_SIZE as u64, RLIM_INFINITY);
|
RLimit64::new(INIT_STACK_SIZE as u64, RLIM_INFINITY).unwrap();
|
||||||
rlimits[ResourceType::RLIMIT_CORE as usize] = RLimit64::new(0, RLIM_INFINITY);
|
rlimits[ResourceType::RLIMIT_CORE as usize] = RLimit64::new(0, RLIM_INFINITY).unwrap();
|
||||||
rlimits[ResourceType::RLIMIT_RSS as usize] = RLimit64::new(RLIM_INFINITY, RLIM_INFINITY);
|
rlimits[ResourceType::RLIMIT_RSS as usize] =
|
||||||
|
RLimit64::new(RLIM_INFINITY, RLIM_INFINITY).unwrap();
|
||||||
rlimits[ResourceType::RLIMIT_NPROC as usize] =
|
rlimits[ResourceType::RLIMIT_NPROC as usize] =
|
||||||
RLimit64::new(INIT_RLIMIT_NPROC, INIT_RLIMIT_NPROC);
|
RLimit64::new(INIT_RLIMIT_NPROC, INIT_RLIMIT_NPROC).unwrap();
|
||||||
rlimits[ResourceType::RLIMIT_NOFILE as usize] =
|
rlimits[ResourceType::RLIMIT_NOFILE as usize] =
|
||||||
RLimit64::new(INIT_RLIMIT_NOFILE_CUR, INIT_RLIMIT_NOFILE_MAX);
|
RLimit64::new(INIT_RLIMIT_NOFILE_CUR, INIT_RLIMIT_NOFILE_MAX).unwrap();
|
||||||
rlimits[ResourceType::RLIMIT_MEMLOCK as usize] =
|
rlimits[ResourceType::RLIMIT_MEMLOCK as usize] =
|
||||||
RLimit64::new(INIT_RLIMIT_MEMLOCK, INIT_RLIMIT_MEMLOCK);
|
RLimit64::new(INIT_RLIMIT_MEMLOCK, INIT_RLIMIT_MEMLOCK).unwrap();
|
||||||
rlimits[ResourceType::RLIMIT_AS as usize] = RLimit64::new(RLIM_INFINITY, RLIM_INFINITY);
|
rlimits[ResourceType::RLIMIT_AS as usize] =
|
||||||
rlimits[ResourceType::RLIMIT_LOCKS as usize] = RLimit64::new(RLIM_INFINITY, RLIM_INFINITY);
|
RLimit64::new(RLIM_INFINITY, RLIM_INFINITY).unwrap();
|
||||||
|
rlimits[ResourceType::RLIMIT_LOCKS as usize] =
|
||||||
|
RLimit64::new(RLIM_INFINITY, RLIM_INFINITY).unwrap();
|
||||||
rlimits[ResourceType::RLIMIT_SIGPENDING as usize] =
|
rlimits[ResourceType::RLIMIT_SIGPENDING as usize] =
|
||||||
RLimit64::new(INIT_RLIMIT_SIGPENDING, INIT_RLIMIT_SIGPENDING);
|
RLimit64::new(INIT_RLIMIT_SIGPENDING, INIT_RLIMIT_SIGPENDING).unwrap();
|
||||||
rlimits[ResourceType::RLIMIT_MSGQUEUE as usize] =
|
rlimits[ResourceType::RLIMIT_MSGQUEUE as usize] =
|
||||||
RLimit64::new(INIT_RLIMIT_MSGQUEUE, INIT_RLIMIT_MSGQUEUE);
|
RLimit64::new(INIT_RLIMIT_MSGQUEUE, INIT_RLIMIT_MSGQUEUE).unwrap();
|
||||||
rlimits[ResourceType::RLIMIT_NICE as usize] =
|
rlimits[ResourceType::RLIMIT_NICE as usize] =
|
||||||
RLimit64::new(INIT_RLIMIT_NICE, INIT_RLIMIT_NICE);
|
RLimit64::new(INIT_RLIMIT_NICE, INIT_RLIMIT_NICE).unwrap();
|
||||||
rlimits[ResourceType::RLIMIT_RTPRIO as usize] =
|
rlimits[ResourceType::RLIMIT_RTPRIO as usize] =
|
||||||
RLimit64::new(INIT_RLIMIT_RTPRIO, INIT_RLIMIT_RTPRIO);
|
RLimit64::new(INIT_RLIMIT_RTPRIO, INIT_RLIMIT_RTPRIO).unwrap();
|
||||||
rlimits[ResourceType::RLIMIT_RTTIME as usize] = RLimit64::new(RLIM_INFINITY, RLIM_INFINITY);
|
rlimits[ResourceType::RLIMIT_RTTIME as usize] =
|
||||||
|
RLimit64::new(RLIM_INFINITY, RLIM_INFINITY).unwrap();
|
||||||
|
|
||||||
ResourceLimits { rlimits }
|
ResourceLimits { rlimits }
|
||||||
}
|
}
|
||||||
@ -97,34 +103,69 @@ pub const RLIMIT_COUNT: usize = 16;
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Pod)]
|
#[derive(Debug, Clone, Copy, Pod)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
pub struct RawRLimit64 {
|
||||||
|
pub cur: u64,
|
||||||
|
pub max: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[repr(C)]
|
||||||
pub struct RLimit64 {
|
pub struct RLimit64 {
|
||||||
cur: u64,
|
cur: AtomicU64,
|
||||||
max: u64,
|
max: AtomicU64,
|
||||||
|
lock: SpinLock<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RLimit64 {
|
impl RLimit64 {
|
||||||
pub fn new(cur: u64, max: u64) -> Self {
|
pub fn new(cur_: u64, max_: u64) -> Result<Self> {
|
||||||
Self { cur, max }
|
if cur_ > max_ {
|
||||||
|
return_errno_with_message!(Errno::EINVAL, "invalid rlimit");
|
||||||
|
}
|
||||||
|
Ok(Self {
|
||||||
|
cur: AtomicU64::new(cur_),
|
||||||
|
max: AtomicU64::new(max_),
|
||||||
|
lock: SpinLock::new(()),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the current rlimit without synchronization.
|
||||||
pub fn get_cur(&self) -> u64 {
|
pub fn get_cur(&self) -> u64 {
|
||||||
self.cur
|
self.cur.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the max rlimit without synchronization.
|
||||||
pub fn get_max(&self) -> u64 {
|
pub fn get_max(&self) -> u64 {
|
||||||
self.max
|
self.max.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_valid(&self) -> bool {
|
/// Gets the rlimit with synchronization.
|
||||||
self.cur <= self.max
|
///
|
||||||
|
/// Only called when handling the `getrlimit` or `prlimit` syscall.
|
||||||
|
pub fn get_cur_and_max(&self) -> (u64, u64) {
|
||||||
|
let _guard = self.lock.lock();
|
||||||
|
(self.get_cur(), self.get_max())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the rlimit with synchronization.
|
||||||
|
///
|
||||||
|
/// Only called when handling the `setrlimit` or `prlimit` syscall.
|
||||||
|
pub fn set_cur_and_max(&self, new_cur: u64, new_max: u64) -> Result<()> {
|
||||||
|
if new_cur > new_max {
|
||||||
|
return_errno_with_message!(Errno::EINVAL, "invalid rlimit");
|
||||||
|
}
|
||||||
|
let _guard = self.lock.lock();
|
||||||
|
self.cur.store(new_cur, Ordering::Relaxed);
|
||||||
|
self.max.store(new_max, Ordering::Relaxed);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for RLimit64 {
|
impl Default for RLimit64 {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
cur: RLIM_INFINITY,
|
cur: AtomicU64::new(RLIM_INFINITY),
|
||||||
max: RLIM_INFINITY,
|
max: AtomicU64::new(RLIM_INFINITY),
|
||||||
|
lock: SpinLock::new(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,6 @@ fn do_dup3(
|
|||||||
>= ctx
|
>= ctx
|
||||||
.process
|
.process
|
||||||
.resource_limits()
|
.resource_limits()
|
||||||
.lock()
|
|
||||||
.get_rlimit(ResourceType::RLIMIT_NOFILE)
|
.get_rlimit(ResourceType::RLIMIT_NOFILE)
|
||||||
.get_cur() as FileDesc
|
.get_cur() as FileDesc
|
||||||
{
|
{
|
||||||
|
@ -48,7 +48,7 @@ fn check_offset_and_len(offset: i64, len: i64, ctx: &Context) -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let max_file_size = {
|
let max_file_size = {
|
||||||
let resource_limits = ctx.process.resource_limits().lock();
|
let resource_limits = ctx.process.resource_limits();
|
||||||
resource_limits
|
resource_limits
|
||||||
.get_rlimit(ResourceType::RLIMIT_FSIZE)
|
.get_rlimit(ResourceType::RLIMIT_FSIZE)
|
||||||
.get_cur() as usize
|
.get_cur() as usize
|
||||||
|
@ -3,15 +3,17 @@
|
|||||||
use super::SyscallReturn;
|
use super::SyscallReturn;
|
||||||
use crate::{
|
use crate::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
process::{rlimit::RLimit64, Pid, ResourceType},
|
process::{rlimit::RawRLimit64, Pid, ResourceType},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn sys_getrlimit(resource: u32, rlim_addr: Vaddr, ctx: &Context) -> Result<SyscallReturn> {
|
pub fn sys_getrlimit(resource: u32, rlim_addr: Vaddr, ctx: &Context) -> Result<SyscallReturn> {
|
||||||
let resource = ResourceType::try_from(resource)?;
|
let resource = ResourceType::try_from(resource)?;
|
||||||
debug!("resource = {:?}, rlim_addr = 0x{:x}", resource, rlim_addr);
|
debug!("resource = {:?}, rlim_addr = 0x{:x}", resource, rlim_addr);
|
||||||
let resource_limits = ctx.process.resource_limits().lock();
|
let resource_limits = ctx.process.resource_limits();
|
||||||
let rlimit = resource_limits.get_rlimit(resource);
|
let rlimit = resource_limits.get_rlimit(resource);
|
||||||
ctx.user_space().write_val(rlim_addr, rlimit)?;
|
let (cur, max) = rlimit.get_cur_and_max();
|
||||||
|
let rlimit_raw = RawRLimit64 { cur, max };
|
||||||
|
ctx.user_space().write_val(rlim_addr, &rlimit_raw)?;
|
||||||
Ok(SyscallReturn::Return(0))
|
Ok(SyscallReturn::Return(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,12 +23,11 @@ pub fn sys_setrlimit(resource: u32, new_rlim_addr: Vaddr, ctx: &Context) -> Resu
|
|||||||
"resource = {:?}, new_rlim_addr = 0x{:x}",
|
"resource = {:?}, new_rlim_addr = 0x{:x}",
|
||||||
resource, new_rlim_addr
|
resource, new_rlim_addr
|
||||||
);
|
);
|
||||||
let new_rlimit: RLimit64 = ctx.user_space().read_val(new_rlim_addr)?;
|
let new_raw: RawRLimit64 = ctx.user_space().read_val(new_rlim_addr)?;
|
||||||
if !new_rlimit.is_valid() {
|
let resource_limits = ctx.process.resource_limits();
|
||||||
return_errno_with_message!(Errno::EINVAL, "invalid rlimit");
|
resource_limits
|
||||||
}
|
.get_rlimit(resource)
|
||||||
let mut resource_limits = ctx.process.resource_limits().lock();
|
.set_cur_and_max(new_raw.cur, new_raw.max)?;
|
||||||
*resource_limits.get_rlimit_mut(resource) = new_rlimit;
|
|
||||||
Ok(SyscallReturn::Return(0))
|
Ok(SyscallReturn::Return(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,18 +43,19 @@ pub fn sys_prlimit64(
|
|||||||
"pid = {}, resource = {:?}, new_rlim_addr = 0x{:x}, old_rlim_addr = 0x{:x}",
|
"pid = {}, resource = {:?}, new_rlim_addr = 0x{:x}, old_rlim_addr = 0x{:x}",
|
||||||
pid, resource, new_rlim_addr, old_rlim_addr
|
pid, resource, new_rlim_addr, old_rlim_addr
|
||||||
);
|
);
|
||||||
let mut resource_limits = ctx.process.resource_limits().lock();
|
let resource_limits = ctx.process.resource_limits();
|
||||||
if old_rlim_addr != 0 {
|
if old_rlim_addr != 0 {
|
||||||
let rlimit = resource_limits.get_rlimit(resource);
|
let rlimit = resource_limits.get_rlimit(resource);
|
||||||
ctx.user_space().write_val(old_rlim_addr, rlimit)?;
|
let (cur, max) = rlimit.get_cur_and_max();
|
||||||
|
let rlimit_raw = RawRLimit64 { cur, max };
|
||||||
|
ctx.user_space().write_val(old_rlim_addr, &rlimit_raw)?;
|
||||||
}
|
}
|
||||||
if new_rlim_addr != 0 {
|
if new_rlim_addr != 0 {
|
||||||
let new_rlimit: RLimit64 = ctx.user_space().read_val(new_rlim_addr)?;
|
let new_raw: RawRLimit64 = ctx.user_space().read_val(new_rlim_addr)?;
|
||||||
debug!("new_rlimit = {:?}", new_rlimit);
|
debug!("new_rlimit = {:?}", new_raw);
|
||||||
if !new_rlimit.is_valid() {
|
resource_limits
|
||||||
return_errno_with_message!(Errno::EINVAL, "invalid rlimit");
|
.get_rlimit(resource)
|
||||||
}
|
.set_cur_and_max(new_raw.cur, new_raw.max)?;
|
||||||
*resource_limits.get_rlimit_mut(resource) = new_rlimit;
|
|
||||||
}
|
}
|
||||||
Ok(SyscallReturn::Return(0))
|
Ok(SyscallReturn::Return(0))
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ fn check_length(len: isize, ctx: &Context) -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let max_file_size = {
|
let max_file_size = {
|
||||||
let resource_limits = ctx.process.resource_limits().lock();
|
let resource_limits = ctx.process.resource_limits();
|
||||||
resource_limits
|
resource_limits
|
||||||
.get_rlimit(ResourceType::RLIMIT_FSIZE)
|
.get_rlimit(ResourceType::RLIMIT_FSIZE)
|
||||||
.get_cur() as usize
|
.get_cur() as usize
|
||||||
|
Loading…
x
Reference in New Issue
Block a user