Add support for sysinfo syscall

This commit is contained in:
Hui, Chunyang 2020-06-02 09:30:17 +00:00 committed by Tate, Hongliang Tian
parent c8a4f2f8aa
commit 6e57937b45
10 changed files with 133 additions and 3 deletions

@ -8,6 +8,7 @@ use crate::exception::*;
use crate::fs::HostStdioFds;
use crate::process::ProcessFilter;
use crate::signal::SigNum;
use crate::time::up_time::init;
use crate::util::log::LevelFilter;
use crate::util::mem_util::from_untrusted::*;
use crate::util::sgx::allow_debug as sgx_allow_debug;
@ -72,6 +73,9 @@ pub extern "C" fn occlum_ecall_init(log_level: *const c_char, instance_dir: *con
}
HAS_INIT.store(true, Ordering::SeqCst);
// Init boot up time stamp here.
time::up_time::init();
});
0

@ -1,7 +1,9 @@
use super::*;
mod rlimit;
mod sysinfo;
mod uname;
pub use self::rlimit::{do_prlimit, resource_t, rlimit_t, ResourceLimits};
pub use self::sysinfo::{do_sysinfo, sysinfo_t};
pub use self::uname::{do_uname, utsname_t};

@ -0,0 +1,35 @@
use super::*;
use crate::process::table;
use crate::time::up_time::get;
use crate::vm::USER_SPACE_VM_MANAGER;
use config::LIBOS_CONFIG;
// This structure aligns with Linux kernels which are later than v2.3.23 (i386) and v2.3.48 (all architectures)
#[repr(C)]
#[derive(Clone, Default)]
pub struct sysinfo_t {
uptime: i64,
loads: [u64; 3],
totalram: u64,
freeram: u64,
sharedram: u64,
bufferram: u64,
totalswap: u64,
freeswap: u64,
procs: u16,
totalhigh: u64,
freehigh: u64,
mem_unit: u32,
}
pub fn do_sysinfo() -> Result<sysinfo_t> {
let info = sysinfo_t {
uptime: time::up_time::get().unwrap().as_secs() as i64, // Duration can't be negative
totalram: USER_SPACE_VM_MANAGER.get_total_size() as u64,
freeram: USER_SPACE_VM_MANAGER.get_free_size() as u64,
procs: table::get_all_processes().len() as u16,
mem_unit: 1,
..Default::default()
};
Ok(info)
}

@ -25,7 +25,7 @@ use crate::fs::{
do_readlink, do_readv, do_rename, do_rmdir, do_sendfile, do_stat, do_sync, do_truncate,
do_unlink, do_write, do_writev, iovec_t, File, FileDesc, FileRef, HostStdioFds, Stat,
};
use crate::misc::{resource_t, rlimit_t, utsname_t};
use crate::misc::{resource_t, rlimit_t, sysinfo_t, utsname_t};
use crate::net::{
do_accept, do_accept4, do_bind, do_connect, do_epoll_create, do_epoll_create1, do_epoll_ctl,
do_epoll_pwait, do_epoll_wait, do_getpeername, do_getsockname, do_getsockopt, do_listen,
@ -176,7 +176,7 @@ macro_rules! process_syscall_table_with_callback {
(Gettimeofday = 96) => do_gettimeofday(tv_u: *mut timeval_t),
(Getrlimit = 97) => handle_unsupported(),
(Getrusage = 98) => handle_unsupported(),
(SysInfo = 99) => handle_unsupported(),
(SysInfo = 99) => do_sysinfo(info: *mut sysinfo_t),
(Times = 100) => handle_unsupported(),
(Ptrace = 101) => handle_unsupported(),
(Getuid = 102) => do_getuid(),
@ -755,6 +755,13 @@ fn do_brk(new_brk_addr: usize) -> Result<isize> {
Ok(ret_brk_addr as isize)
}
fn do_sysinfo(info: *mut sysinfo_t) -> Result<isize> {
check_mut_ptr(info)?;
let info = unsafe { &mut *info };
*info = misc::do_sysinfo()?;
Ok(0)
}
// TODO: handle tz: timezone_t
fn do_gettimeofday(tv_u: *mut timeval_t) -> Result<isize> {
check_mut_ptr(tv_u)?;

@ -8,6 +8,7 @@ use std::{fmt, u64};
use syscall::SyscallNum;
mod profiler;
pub mod up_time;
pub use profiler::GLOBAL_PROFILER;

@ -0,0 +1,19 @@
use super::{do_clock_gettime, ClockID};
use std::time::Duration;
lazy_static! {
static ref BOOT_TIME_STAMP: Duration = do_clock_gettime(ClockID::CLOCK_MONOTONIC_RAW)
.unwrap()
.as_duration();
}
pub fn init() {
*BOOT_TIME_STAMP;
}
pub fn get() -> Option<Duration> {
do_clock_gettime(ClockID::CLOCK_MONOTONIC_RAW)
.unwrap()
.as_duration()
.checked_sub(*BOOT_TIME_STAMP)
}

@ -13,6 +13,7 @@ use self::vm_layout::VMLayout;
use self::vm_manager::{VMManager, VMMapOptionsBuilder};
pub use self::process_vm::{MMapFlags, MRemapFlags, ProcessVM, ProcessVMBuilder, VMPerms};
pub use self::user_space_vm::USER_SPACE_VM_MANAGER;
pub use self::vm_range::VMRange;
pub fn do_mmap(

@ -22,7 +22,7 @@ TEST_DEPS := client data_sink
TESTS ?= env empty hello_world malloc mmap file fs_perms getpid spawn sched pipe time \
truncate readdir mkdir open stat link symlink chmod chown tls pthread uname rlimit \
server server_epoll unix_socket cout hostfs cpuid rdtsc device sleep exit_group \
ioctl fcntl eventfd emulate_syscall access signal
ioctl fcntl eventfd emulate_syscall access signal sysinfo
# Benchmarks: need to be compiled and run by bench-% target
BENCHES := spawn_and_exit_latency pipe_throughput unix_socket_throughput

5
test/sysinfo/Makefile Normal file

@ -0,0 +1,5 @@
include ../test_common.mk
EXTRA_C_FLAGS :=
EXTRA_LINK_FLAGS :=
BIN_ARGS :=

56
test/sysinfo/main.c Normal file

@ -0,0 +1,56 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/sysinfo.h>
#include <spawn.h>
#include <sys/wait.h>
#include "test.h"
int test_sysinfo() {
const long MIN = 60;
const long HOUR = MIN * 60;
const long DAY = HOUR * 24;
const double MEGABYTE = 1024 * 1024;
struct sysinfo info;
int child_pid, status;
// Test uptime
sleep(3);
// Test procs number
int ret = posix_spawn(&child_pid, "/bin/getpid", NULL, NULL, NULL, NULL);
if (ret < 0 ) {
THROW_ERROR("spawn process error");
}
sysinfo (&info);
printf ("system uptime: %ld days, %ld:%02ld:%02ld\n",
info.uptime / DAY, (info.uptime % DAY) / HOUR,
(info.uptime % HOUR) / MIN, info.uptime % MIN);
printf ("total RAM: %5.1f MB\n", info.totalram / MEGABYTE);
printf ("free RAM: %5.1f MB\n", info.freeram / MEGABYTE);
printf ("process count: %d\n", info.procs);
if (info.uptime % MIN < 3) {
THROW_ERROR("system uptime error");
}
if (info.procs != 2 ) {
THROW_ERROR("system process count error");
}
ret = wait4(-1, &status, 0, NULL);
if (ret < 0) {
THROW_ERROR("failed to wait4 the child proces");
}
return 0;
}
static test_case_t test_cases[] = {
TEST_CASE(test_sysinfo),
};
int main() {
return test_suite_run(test_cases, ARRAY_SIZE(test_cases));
}