Add prlimit64, getrlimit, and setrlimit
This commit is contained in:
parent
8846c62b5e
commit
b003f4ce43
@ -1,5 +1,7 @@
|
||||
use super::*;
|
||||
|
||||
mod uname;
|
||||
mod rlimit;
|
||||
|
||||
pub use self::uname::{utsname_t, do_uname};
|
||||
pub use self::rlimit::{rlimit_t, resource_t, ResourceLimits, ResourceLimitsRef, do_prlimit};
|
||||
|
123
src/libos/src/misc/rlimit.rs
Normal file
123
src/libos/src/misc/rlimit.rs
Normal file
@ -0,0 +1,123 @@
|
||||
use super::*;
|
||||
use process::{pid_t};
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct ResourceLimits {
|
||||
rlimits: [rlimit_t; RLIMIT_COUNT],
|
||||
}
|
||||
pub type ResourceLimitsRef = Arc<SgxMutex<ResourceLimits>>;
|
||||
|
||||
impl ResourceLimits {
|
||||
pub fn get(&self, resource: resource_t) -> &rlimit_t {
|
||||
&self.rlimits[resource as usize]
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self, resource: resource_t) -> &mut rlimit_t {
|
||||
&mut self.rlimits[resource as usize]
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ResourceLimits {
|
||||
fn default() -> ResourceLimits {
|
||||
// TODO: set appropriate limits for resources
|
||||
let mut rlimits = ResourceLimits {
|
||||
rlimits: [ Default::default(); RLIMIT_COUNT ],
|
||||
};
|
||||
rlimits
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct rlimit_t {
|
||||
cur: u64,
|
||||
max: u64,
|
||||
}
|
||||
|
||||
impl Default for rlimit_t {
|
||||
fn default() -> rlimit_t {
|
||||
rlimit_t {
|
||||
cur: u64::max_value(),
|
||||
max: u64::max_value(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum resource_t {
|
||||
RLIMIT_CPU = 0,
|
||||
RLIMIT_FSIZE = 1,
|
||||
RLIMIT_DATA = 2,
|
||||
RLIMIT_STACK = 3,
|
||||
RLIMIT_CORE = 4,
|
||||
RLIMIT_RSS = 5,
|
||||
RLIMIT_NPROC = 6,
|
||||
RLIMIT_NOFILE = 7,
|
||||
RLIMIT_MEMLOCK = 8,
|
||||
RLIMIT_AS = 9,
|
||||
RLIMIT_LOCKS = 10,
|
||||
RLIMIT_SIGPENDING = 11,
|
||||
RLIMIT_MSGQUEUE = 12,
|
||||
RLIMIT_NICE = 13,
|
||||
RLIMIT_RTPRIO = 14,
|
||||
}
|
||||
const RLIMIT_COUNT: usize = 15;
|
||||
|
||||
impl resource_t {
|
||||
pub fn from_u32(bits: u32) -> Result<resource_t, Error> {
|
||||
match bits {
|
||||
0 => Ok(resource_t::RLIMIT_CPU),
|
||||
1 => Ok(resource_t::RLIMIT_FSIZE),
|
||||
2 => Ok(resource_t::RLIMIT_DATA),
|
||||
3 => Ok(resource_t::RLIMIT_STACK),
|
||||
4 => Ok(resource_t::RLIMIT_CORE),
|
||||
5 => Ok(resource_t::RLIMIT_RSS),
|
||||
6 => Ok(resource_t::RLIMIT_NPROC),
|
||||
7 => Ok(resource_t::RLIMIT_NOFILE),
|
||||
8 => Ok(resource_t::RLIMIT_MEMLOCK),
|
||||
9 => Ok(resource_t::RLIMIT_AS),
|
||||
10 => Ok(resource_t::RLIMIT_LOCKS),
|
||||
11 => Ok(resource_t::RLIMIT_SIGPENDING),
|
||||
12 => Ok(resource_t::RLIMIT_MSGQUEUE),
|
||||
13 => Ok(resource_t::RLIMIT_NICE),
|
||||
14 => Ok(resource_t::RLIMIT_RTPRIO),
|
||||
_ => errno!(EINVAL, "invalid resource"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn do_prlimit(
|
||||
pid: pid_t,
|
||||
resource: resource_t,
|
||||
new_limit: Option<&rlimit_t>,
|
||||
old_limit: Option<&mut rlimit_t>,
|
||||
) -> Result<(), Error> {
|
||||
let process_ref = if pid == 0 {
|
||||
process::get_current()
|
||||
}
|
||||
else {
|
||||
process::get(pid)?
|
||||
};
|
||||
let mut process = process_ref.lock().unwrap();
|
||||
let rlimits_ref = process.get_rlimits();
|
||||
let mut rlimits = rlimits_ref.lock().unwrap();
|
||||
if let Some(old_limit) = old_limit {
|
||||
*old_limit = *rlimits.get(resource)
|
||||
}
|
||||
if let Some(new_limit) = new_limit {
|
||||
*rlimits.get_mut(resource) = *new_limit;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn do_getrlimit(resource: resource_t, old_limit: &mut rlimit_t) -> Result<(), Error> {
|
||||
do_prlimit(0 as pid_t, resource, None, Some(old_limit))
|
||||
}
|
||||
|
||||
pub fn do_setrlimit(resource: resource_t, new_limit: &rlimit_t) -> Result<(), Error> {
|
||||
do_prlimit(0 as pid_t, resource, Some(new_limit), None)
|
||||
}
|
@ -1,8 +1,6 @@
|
||||
pub use self::process::{Status, IDLE_PROCESS};
|
||||
pub use self::task::{get_current, run_task};
|
||||
pub mod table {
|
||||
pub use super::process_table::get;
|
||||
}
|
||||
pub use self::process_table::{get};
|
||||
pub use self::exit::{do_exit, do_wait4, ChildProcessFilter};
|
||||
pub use self::spawn::{do_spawn, FileAction};
|
||||
pub use self::wait::{WaitQueue, Waiter};
|
||||
@ -30,6 +28,7 @@ pub struct Process {
|
||||
waiting_children: Option<WaitQueue<ChildProcessFilter, pid_t>>,
|
||||
vm: ProcessVMRef,
|
||||
file_table: FileTableRef,
|
||||
rlimits: ResourceLimitsRef,
|
||||
}
|
||||
|
||||
pub type ProcessRef = Arc<SgxMutex<Process>>;
|
||||
@ -79,3 +78,4 @@ use self::task::Task;
|
||||
use super::*;
|
||||
use fs::{File, FileRef, FileTable};
|
||||
use vm::{ProcessVM, VMRangeTrait};
|
||||
use misc::{ResourceLimitsRef};
|
||||
|
@ -20,6 +20,7 @@ lazy_static! {
|
||||
waiting_children: Default::default(),
|
||||
vm: Default::default(),
|
||||
file_table: Default::default(),
|
||||
rlimits: Default::default(),
|
||||
}))
|
||||
};
|
||||
}
|
||||
@ -30,6 +31,7 @@ impl Process {
|
||||
task: Task,
|
||||
vm_ref: ProcessVMRef,
|
||||
file_table_ref: FileTableRef,
|
||||
rlimits_ref: ResourceLimitsRef,
|
||||
) -> Result<(pid_t, ProcessRef), Error> {
|
||||
let new_pid = process_table::alloc_pid();
|
||||
let new_process_ref = Arc::new(SgxMutex::new(Process {
|
||||
@ -46,6 +48,7 @@ impl Process {
|
||||
waiting_children: None,
|
||||
vm: vm_ref,
|
||||
file_table: file_table_ref,
|
||||
rlimits: rlimits_ref,
|
||||
}));
|
||||
Ok((new_pid, new_process_ref))
|
||||
}
|
||||
@ -97,6 +100,9 @@ impl Process {
|
||||
self.cwd += path;
|
||||
}
|
||||
}
|
||||
pub fn get_rlimits(&self) -> &ResourceLimitsRef {
|
||||
&self.rlimits
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Process {
|
||||
|
@ -14,8 +14,10 @@ pub fn remove(pid: pid_t) {
|
||||
PROCESS_TABLE.lock().unwrap().remove(&pid);
|
||||
}
|
||||
|
||||
pub fn get(pid: pid_t) -> Option<ProcessRef> {
|
||||
PROCESS_TABLE.lock().unwrap().get(&pid).map(|pr| pr.clone())
|
||||
pub fn get(pid: pid_t) -> Result<ProcessRef, Error> {
|
||||
PROCESS_TABLE.lock().unwrap().get(&pid)
|
||||
.map(|pr| pr.clone())
|
||||
.ok_or_else(|| Error::new(Errno::ENOENT, "process not found"))
|
||||
}
|
||||
|
||||
static NEXT_PID: AtomicU32 = AtomicU32::new(1);
|
||||
|
@ -6,6 +6,7 @@ use std::ffi::{CStr, CString};
|
||||
use std::path::Path;
|
||||
use std::sgxfs::SgxFile;
|
||||
use vm::{ProcessVM, VMRangeTrait};
|
||||
use misc::{ResourceLimitsRef};
|
||||
|
||||
use super::*;
|
||||
use super::task::Task;
|
||||
@ -72,7 +73,8 @@ pub fn do_spawn<P: AsRef<Path>>(
|
||||
let files = init_files(parent_ref, file_actions)?;
|
||||
Arc::new(SgxMutex::new(files))
|
||||
};
|
||||
Process::new(&cwd, task, vm_ref, files_ref)?
|
||||
let rlimits_ref = Default::default();
|
||||
Process::new(&cwd, task, vm_ref, files_ref, rlimits_ref)?
|
||||
};
|
||||
parent_adopts_new_child(&parent_ref, &new_process_ref);
|
||||
process_table::put(new_pid, new_process_ref.clone());
|
||||
|
@ -51,8 +51,9 @@ pub fn do_clone(
|
||||
let task = new_thread_task(stack_addr, new_tls)?;
|
||||
let vm_ref = current.get_vm().clone();
|
||||
let files_ref = current.get_files().clone();
|
||||
let rlimits_ref = current.get_rlimits().clone();
|
||||
let cwd = ¤t.cwd;
|
||||
Process::new(cwd, task, vm_ref, files_ref)?
|
||||
Process::new(cwd, task, vm_ref, files_ref, rlimits_ref)?
|
||||
};
|
||||
|
||||
if let Some(ctid) = ctid {
|
||||
|
@ -8,7 +8,7 @@ use std::ptr;
|
||||
use time::timeval_t;
|
||||
use util::mem_util::from_user::*;
|
||||
use vm::{VMAreaFlags, VMResizeOptions};
|
||||
use misc::{utsname_t};
|
||||
use misc::{utsname_t, resource_t, rlimit_t};
|
||||
|
||||
use super::*;
|
||||
|
||||
@ -134,6 +134,8 @@ pub extern "C" fn dispatch_syscall(
|
||||
|
||||
SYS_UNAME => do_uname(arg0 as *mut utsname_t),
|
||||
|
||||
SYS_PRLIMIT64 => do_prlimit(arg0 as pid_t, arg1 as u32, arg2 as *const rlimit_t, arg3 as *mut rlimit_t),
|
||||
|
||||
_ => do_unknown(num, arg0, arg1, arg2, arg3, arg4, arg5),
|
||||
};
|
||||
debug!("syscall return: {:?}", ret);
|
||||
@ -705,3 +707,26 @@ fn do_uname(name: *mut utsname_t) -> Result<isize, Error> {
|
||||
let name = unsafe { &mut *name };
|
||||
misc::do_uname(name).map(|_| 0)
|
||||
}
|
||||
|
||||
fn do_prlimit(pid: pid_t, resource: u32, new_limit: *const rlimit_t, old_limit: *mut rlimit_t) -> Result<isize, Error> {
|
||||
let resource = resource_t::from_u32(resource)?;
|
||||
let new_limit = {
|
||||
if new_limit != ptr::null() {
|
||||
check_ptr(new_limit)?;
|
||||
Some(unsafe { &*new_limit })
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
};
|
||||
let old_limit = {
|
||||
if old_limit != ptr::null_mut() {
|
||||
check_mut_ptr(old_limit)?;
|
||||
Some(unsafe { &mut *old_limit })
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
};
|
||||
misc::do_prlimit(pid, resource, new_limit, old_limit).map(|_| 0)
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ PROJECT_DIR := $(realpath $(CUR_DIR)/../)
|
||||
# Dependencies: need to be compiled but not to run by any Makefile target
|
||||
TEST_DEPS := dev_null
|
||||
# Tests: need to be compiled and run by test-% target
|
||||
TESTS := empty argv hello_world malloc file getpid spawn pipe time truncate readdir mkdir link tls pthread uname
|
||||
TESTS := empty argv hello_world malloc file getpid spawn pipe time truncate readdir mkdir link tls pthread uname rlimit
|
||||
# Benchmarks: need to be compiled and run by bench-% target
|
||||
BENCHES := spawn_and_exit_latency pipe_throughput
|
||||
|
||||
|
5
test/rlimit/Makefile
Normal file
5
test/rlimit/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
include ../test_common.mk
|
||||
|
||||
EXTRA_C_FLAGS :=
|
||||
EXTRA_LINK_FLAGS :=
|
||||
BIN_ARGS :=
|
15
test/rlimit/main.c
Normal file
15
test/rlimit/main.c
Normal file
@ -0,0 +1,15 @@
|
||||
#include <sys/resource.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
struct rlimit rlim;
|
||||
if (getrlimit(RLIMIT_AS, &rlim) < 0) {
|
||||
printf("ERROR: getrlimit failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (setrlimit(RLIMIT_AS, &rlim) < 0) {
|
||||
printf("ERROR: getrlimit failed\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user