diff --git a/src/Enclave.edl b/src/Enclave.edl index faa833ef..05234cc7 100644 --- a/src/Enclave.edl +++ b/src/Enclave.edl @@ -50,6 +50,8 @@ enclave { */ int occlum_ocall_exec_thread_async(int libos_tid); + int occlum_ocall_thread_getcpuclock([out] struct timespec* ts) propagate_errno; + void occlum_ocall_gettimeofday([out] struct timeval* tv); void occlum_ocall_clock_gettime(clockid_t clockid, [out] struct timespec* ts); diff --git a/src/libos/src/process/mod.rs b/src/libos/src/process/mod.rs index 953f1ca8..1f22ffe6 100644 --- a/src/libos/src/process/mod.rs +++ b/src/libos/src/process/mod.rs @@ -86,4 +86,5 @@ use self::task::Task; use super::*; use fs::{File, FileRef, FileTable}; use misc::ResourceLimitsRef; +use time::GLOBAL_PROFILER; use vm::ProcessVM; diff --git a/src/libos/src/process/task.rs b/src/libos/src/process/task.rs index 042a61a7..4277aa7a 100644 --- a/src/libos/src/process/task.rs +++ b/src/libos/src/process/task.rs @@ -98,11 +98,25 @@ pub fn run_task(libos_tid: pid_t, host_tid: pid_t) -> Result { (pid, task) }; + #[cfg(feature = "syscall_timing")] + GLOBAL_PROFILER + .lock() + .unwrap() + .thread_enter() + .expect("unexpected error from profiler to enter thread"); + unsafe { // task may only be modified by this function; so no lock is needed do_run_task(task); } + #[cfg(feature = "syscall_timing")] + GLOBAL_PROFILER + .lock() + .unwrap() + .thread_exit() + .expect("unexpected error from profiler to exit thread"); + let (exit_status, parent_pid) = { let mut process = new_process.lock().unwrap(); let parent = process.get_parent().lock().unwrap(); diff --git a/src/libos/src/syscall/consts.rs b/src/libos/src/syscall/consts.rs deleted file mode 100644 index 781059d1..00000000 --- a/src/libos/src/syscall/consts.rs +++ /dev/null @@ -1,330 +0,0 @@ -//! Syscall numbers - -pub const SYS_READ: u32 = 0; -pub const SYS_WRITE: u32 = 1; -pub const SYS_OPEN: u32 = 2; -pub const SYS_CLOSE: u32 = 3; -pub const SYS_STAT: u32 = 4; -pub const SYS_FSTAT: u32 = 5; -pub const SYS_LSTAT: u32 = 6; -pub const SYS_POLL: u32 = 7; -pub const SYS_LSEEK: u32 = 8; -pub const SYS_MMAP: u32 = 9; -pub const SYS_MPROTECT: u32 = 10; -pub const SYS_MUNMAP: u32 = 11; -pub const SYS_BRK: u32 = 12; -pub const SYS_RT_SIGACTION: u32 = 13; -pub const SYS_RT_SIGPROCMASK: u32 = 14; -pub const SYS_RT_SIGRETURN: u32 = 15; -pub const SYS_IOCTL: u32 = 16; -pub const SYS_PREAD64: u32 = 17; -pub const SYS_PWRITE64: u32 = 18; -pub const SYS_READV: u32 = 19; -pub const SYS_WRITEV: u32 = 20; -pub const SYS_ACCESS: u32 = 21; -pub const SYS_PIPE: u32 = 22; -pub const SYS_SELECT: u32 = 23; -pub const SYS_SCHED_YIELD: u32 = 24; -pub const SYS_MREMAP: u32 = 25; -pub const SYS_MSYNC: u32 = 26; -pub const SYS_MINCORE: u32 = 27; -pub const SYS_MADVISE: u32 = 28; -pub const SYS_SHMGET: u32 = 29; -pub const SYS_SHMAT: u32 = 30; -pub const SYS_SHMCTL: u32 = 31; -pub const SYS_DUP: u32 = 32; -pub const SYS_DUP2: u32 = 33; -pub const SYS_PAUSE: u32 = 34; -pub const SYS_NANOSLEEP: u32 = 35; -pub const SYS_GETITIMER: u32 = 36; -pub const SYS_ALARM: u32 = 37; -pub const SYS_SETITIMER: u32 = 38; -pub const SYS_GETPID: u32 = 39; -pub const SYS_SENDFILE: u32 = 40; -pub const SYS_SOCKET: u32 = 41; -pub const SYS_CONNECT: u32 = 42; -pub const SYS_ACCEPT: u32 = 43; -pub const SYS_SENDTO: u32 = 44; -pub const SYS_RECVFROM: u32 = 45; -pub const SYS_SENDMSG: u32 = 46; -pub const SYS_RECVMSG: u32 = 47; -pub const SYS_SHUTDOWN: u32 = 48; -pub const SYS_BIND: u32 = 49; -pub const SYS_LISTEN: u32 = 50; -pub const SYS_GETSOCKNAME: u32 = 51; -pub const SYS_GETPEERNAME: u32 = 52; -pub const SYS_SOCKETPAIR: u32 = 53; -pub const SYS_SETSOCKOPT: u32 = 54; -pub const SYS_GETSOCKOPT: u32 = 55; -pub const SYS_CLONE: u32 = 56; -pub const SYS_FORK: u32 = 57; -pub const SYS_VFORK: u32 = 58; -pub const SYS_EXECVE: u32 = 59; -pub const SYS_EXIT: u32 = 60; -pub const SYS_WAIT4: u32 = 61; -pub const SYS_KILL: u32 = 62; -pub const SYS_UNAME: u32 = 63; -pub const SYS_SEMGET: u32 = 64; -pub const SYS_SEMOP: u32 = 65; -pub const SYS_SEMCTL: u32 = 66; -pub const SYS_SHMDT: u32 = 67; -pub const SYS_MSGGET: u32 = 68; -pub const SYS_MSGSND: u32 = 69; -pub const SYS_MSGRCV: u32 = 70; -pub const SYS_MSGCTL: u32 = 71; -pub const SYS_FCNTL: u32 = 72; -pub const SYS_FLOCK: u32 = 73; -pub const SYS_FSYNC: u32 = 74; -pub const SYS_FDATASYNC: u32 = 75; -pub const SYS_TRUNCATE: u32 = 76; -pub const SYS_FTRUNCATE: u32 = 77; -pub const SYS_GETDENTS: u32 = 78; -pub const SYS_GETCWD: u32 = 79; -pub const SYS_CHDIR: u32 = 80; -pub const SYS_FCHDIR: u32 = 81; -pub const SYS_RENAME: u32 = 82; -pub const SYS_MKDIR: u32 = 83; -pub const SYS_RMDIR: u32 = 84; -pub const SYS_CREAT: u32 = 85; -pub const SYS_LINK: u32 = 86; -pub const SYS_UNLINK: u32 = 87; -pub const SYS_SYMLINK: u32 = 88; -pub const SYS_READLINK: u32 = 89; -pub const SYS_CHMOD: u32 = 90; -pub const SYS_FCHMOD: u32 = 91; -pub const SYS_CHOWN: u32 = 92; -pub const SYS_FCHOWN: u32 = 93; -pub const SYS_LCHOWN: u32 = 94; -pub const SYS_UMASK: u32 = 95; -pub const SYS_GETTIMEOFDAY: u32 = 96; -pub const SYS_GETRLIMIT: u32 = 97; -pub const SYS_GETRUSAGE: u32 = 98; -pub const SYS_SYSINFO: u32 = 99; -pub const SYS_TIMES: u32 = 100; -pub const SYS_PTRACE: u32 = 101; -pub const SYS_GETUID: u32 = 102; -pub const SYS_SYSLOG: u32 = 103; -pub const SYS_GETGID: u32 = 104; -pub const SYS_SETUID: u32 = 105; -pub const SYS_SETGID: u32 = 106; -pub const SYS_GETEUID: u32 = 107; -pub const SYS_GETEGID: u32 = 108; -pub const SYS_SETPGID: u32 = 109; -pub const SYS_GETPPID: u32 = 110; -pub const SYS_GETPGRP: u32 = 111; -pub const SYS_SETSID: u32 = 112; -pub const SYS_SETREUID: u32 = 113; -pub const SYS_SETREGID: u32 = 114; -pub const SYS_GETGROUPS: u32 = 115; -pub const SYS_SETGROUPS: u32 = 116; -pub const SYS_SETRESUID: u32 = 117; -pub const SYS_GETRESUID: u32 = 118; -pub const SYS_SETRESGID: u32 = 119; -pub const SYS_GETRESGID: u32 = 120; -pub const SYS_GETPGID: u32 = 121; -pub const SYS_SETFSUID: u32 = 122; -pub const SYS_SETFSGID: u32 = 123; -pub const SYS_GETSID: u32 = 124; -pub const SYS_CAPGET: u32 = 125; -pub const SYS_CAPSET: u32 = 126; -pub const SYS_RT_SIGPENDING: u32 = 127; -pub const SYS_RT_SIGTIMEDWAIT: u32 = 128; -pub const SYS_RT_SIGQUEUEINFO: u32 = 129; -pub const SYS_RT_SIGSUSPEND: u32 = 130; -pub const SYS_SIGALTSTACK: u32 = 131; -pub const SYS_UTIME: u32 = 132; -pub const SYS_MKNOD: u32 = 133; -pub const SYS_USELIB: u32 = 134; -pub const SYS_PERSONALITY: u32 = 135; -pub const SYS_USTAT: u32 = 136; -pub const SYS_STATFS: u32 = 137; -pub const SYS_FSTATFS: u32 = 138; -pub const SYS_SYSFS: u32 = 139; -pub const SYS_GETPRIORITY: u32 = 140; -pub const SYS_SETPRIORITY: u32 = 141; -pub const SYS_SCHED_SETPARAM: u32 = 142; -pub const SYS_SCHED_GETPARAM: u32 = 143; -pub const SYS_SCHED_SETSCHEDULER: u32 = 144; -pub const SYS_SCHED_GETSCHEDULER: u32 = 145; -pub const SYS_SCHED_GET_PRIORITY_MAX: u32 = 146; -pub const SYS_SCHED_GET_PRIORITY_MIN: u32 = 147; -pub const SYS_SCHED_RR_GET_INTERVAL: u32 = 148; -pub const SYS_MLOCK: u32 = 149; -pub const SYS_MUNLOCK: u32 = 150; -pub const SYS_MLOCKALL: u32 = 151; -pub const SYS_MUNLOCKALL: u32 = 152; -pub const SYS_VHANGUP: u32 = 153; -pub const SYS_MODIFY_LDT: u32 = 154; -pub const SYS_PIVOT_ROOT: u32 = 155; -pub const SYS__SYSCTL: u32 = 156; -pub const SYS_PRCTL: u32 = 157; -pub const SYS_ARCH_PRCTL: u32 = 158; -pub const SYS_ADJTIMEX: u32 = 159; -pub const SYS_SETRLIMIT: u32 = 160; -pub const SYS_CHROOT: u32 = 161; -pub const SYS_SYNC: u32 = 162; -pub const SYS_ACCT: u32 = 163; -pub const SYS_SETTIMEOFDAY: u32 = 164; -pub const SYS_MOUNT: u32 = 165; -pub const SYS_UMOUNT2: u32 = 166; -pub const SYS_SWAPON: u32 = 167; -pub const SYS_SWAPOFF: u32 = 168; -pub const SYS_REBOOT: u32 = 169; -pub const SYS_SETHOSTNAME: u32 = 170; -pub const SYS_SETDOMAINNAME: u32 = 171; -pub const SYS_IOPL: u32 = 172; -pub const SYS_IOPERM: u32 = 173; -pub const SYS_CREATE_MODULE: u32 = 174; -pub const SYS_INIT_MODULE: u32 = 175; -pub const SYS_DELETE_MODULE: u32 = 176; -pub const SYS_GET_KERNEL_SYMS: u32 = 177; -pub const SYS_QUERY_MODULE: u32 = 178; -pub const SYS_QUOTACTL: u32 = 179; -pub const SYS_NFSSERVCTL: u32 = 180; -pub const SYS_GETPMSG: u32 = 181; -pub const SYS_PUTPMSG: u32 = 182; -pub const SYS_AFS_SYSCALL: u32 = 183; -pub const SYS_TUXCALL: u32 = 184; -pub const SYS_SECURITY: u32 = 185; -pub const SYS_GETTID: u32 = 186; -pub const SYS_READAHEAD: u32 = 187; -pub const SYS_SETXATTR: u32 = 188; -pub const SYS_LSETXATTR: u32 = 189; -pub const SYS_FSETXATTR: u32 = 190; -pub const SYS_GETXATTR: u32 = 191; -pub const SYS_LGETXATTR: u32 = 192; -pub const SYS_FGETXATTR: u32 = 193; -pub const SYS_LISTXATTR: u32 = 194; -pub const SYS_LLISTXATTR: u32 = 195; -pub const SYS_FLISTXATTR: u32 = 196; -pub const SYS_REMOVEXATTR: u32 = 197; -pub const SYS_LREMOVEXATTR: u32 = 198; -pub const SYS_FREMOVEXATTR: u32 = 199; -pub const SYS_TKILL: u32 = 200; -pub const SYS_TIME: u32 = 201; -pub const SYS_FUTEX: u32 = 202; -pub const SYS_SCHED_SETAFFINITY: u32 = 203; -pub const SYS_SCHED_GETAFFINITY: u32 = 204; -pub const SYS_SET_THREAD_AREA: u32 = 205; -pub const SYS_IO_SETUP: u32 = 206; -pub const SYS_IO_DESTROY: u32 = 207; -pub const SYS_IO_GETEVENTS: u32 = 208; -pub const SYS_IO_SUBMIT: u32 = 209; -pub const SYS_IO_CANCEL: u32 = 210; -pub const SYS_GET_THREAD_AREA: u32 = 211; -pub const SYS_LOOKUP_DCOOKIE: u32 = 212; -pub const SYS_EPOLL_CREATE: u32 = 213; -pub const SYS_EPOLL_CTL_OLD: u32 = 214; -pub const SYS_EPOLL_WAIT_OLD: u32 = 215; -pub const SYS_REMAP_FILE_PAGES: u32 = 216; -pub const SYS_GETDENTS64: u32 = 217; -pub const SYS_SET_TID_ADDRESS: u32 = 218; -pub const SYS_RESTART_SYSCALL: u32 = 219; -pub const SYS_SEMTIMEDOP: u32 = 220; -pub const SYS_FADVISE64: u32 = 221; -pub const SYS_TIMER_CREATE: u32 = 222; -pub const SYS_TIMER_SETTIME: u32 = 223; -pub const SYS_TIMER_GETTIME: u32 = 224; -pub const SYS_TIMER_GETOVERRUN: u32 = 225; -pub const SYS_TIMER_DELETE: u32 = 226; -pub const SYS_CLOCK_SETTIME: u32 = 227; -pub const SYS_CLOCK_GETTIME: u32 = 228; -pub const SYS_CLOCK_GETRES: u32 = 229; -pub const SYS_CLOCK_NANOSLEEP: u32 = 230; -pub const SYS_EXIT_GROUP: u32 = 231; -pub const SYS_EPOLL_WAIT: u32 = 232; -pub const SYS_EPOLL_CTL: u32 = 233; -pub const SYS_TGKILL: u32 = 234; -pub const SYS_UTIMES: u32 = 235; -pub const SYS_VSERVER: u32 = 236; -pub const SYS_MBIND: u32 = 237; -pub const SYS_SET_MEMPOLICY: u32 = 238; -pub const SYS_GET_MEMPOLICY: u32 = 239; -pub const SYS_MQ_OPEN: u32 = 240; -pub const SYS_MQ_UNLINK: u32 = 241; -pub const SYS_MQ_TIMEDSEND: u32 = 242; -pub const SYS_MQ_TIMEDRECEIVE: u32 = 243; -pub const SYS_MQ_NOTIFY: u32 = 244; -pub const SYS_MQ_GETSETATTR: u32 = 245; -pub const SYS_KEXEC_LOAD: u32 = 246; -pub const SYS_WAITID: u32 = 247; -pub const SYS_ADD_KEY: u32 = 248; -pub const SYS_REQUEST_KEY: u32 = 249; -pub const SYS_KEYCTL: u32 = 250; -pub const SYS_IOPRIO_SET: u32 = 251; -pub const SYS_IOPRIO_GET: u32 = 252; -pub const SYS_INOTIFY_INIT: u32 = 253; -pub const SYS_INOTIFY_ADD_WATCH: u32 = 254; -pub const SYS_INOTIFY_RM_WATCH: u32 = 255; -pub const SYS_MIGRATE_PAGES: u32 = 256; -pub const SYS_OPENAT: u32 = 257; -pub const SYS_MKDIRAT: u32 = 258; -pub const SYS_MKNODAT: u32 = 259; -pub const SYS_FCHOWNAT: u32 = 260; -pub const SYS_FUTIMESAT: u32 = 261; -pub const SYS_NEWFSTATAT: u32 = 262; -pub const SYS_UNLINKAT: u32 = 263; -pub const SYS_RENAMEAT: u32 = 264; -pub const SYS_LINKAT: u32 = 265; -pub const SYS_SYMLINKAT: u32 = 266; -pub const SYS_READLINKAT: u32 = 267; -pub const SYS_FCHMODAT: u32 = 268; -pub const SYS_FACCESSAT: u32 = 269; -pub const SYS_PSELECT6: u32 = 270; -pub const SYS_PPOLL: u32 = 271; -pub const SYS_UNSHARE: u32 = 272; -pub const SYS_SET_ROBUST_LIST: u32 = 273; -pub const SYS_GET_ROBUST_LIST: u32 = 274; -pub const SYS_SPLICE: u32 = 275; -pub const SYS_TEE: u32 = 276; -pub const SYS_SYNC_FILE_RANGE: u32 = 277; -pub const SYS_VMSPLICE: u32 = 278; -pub const SYS_MOVE_PAGES: u32 = 279; -pub const SYS_UTIMENSAT: u32 = 280; -pub const SYS_EPOLL_PWAIT: u32 = 281; -pub const SYS_SIGNALFD: u32 = 282; -pub const SYS_TIMERFD_CREATE: u32 = 283; -pub const SYS_EVENTFD: u32 = 284; -pub const SYS_FALLOCATE: u32 = 285; -pub const SYS_TIMERFD_SETTIME: u32 = 286; -pub const SYS_TIMERFD_GETTIME: u32 = 287; -pub const SYS_ACCEPT4: u32 = 288; -pub const SYS_SIGNALFD4: u32 = 289; -pub const SYS_EVENTFD2: u32 = 290; -pub const SYS_EPOLL_CREATE1: u32 = 291; -pub const SYS_DUP3: u32 = 292; -pub const SYS_PIPE2: u32 = 293; -pub const SYS_INOTIFY_INIT1: u32 = 294; -pub const SYS_PREADV: u32 = 295; -pub const SYS_PWRITEV: u32 = 296; -pub const SYS_RT_TGSIGQUEUEINFO: u32 = 297; -pub const SYS_PERF_EVENT_OPEN: u32 = 298; -pub const SYS_RECVMMSG: u32 = 299; -pub const SYS_FANOTIFY_INIT: u32 = 300; -pub const SYS_FANOTIFY_MARK: u32 = 301; -pub const SYS_PRLIMIT64: u32 = 302; -pub const SYS_NAME_TO_HANDLE_AT: u32 = 303; -pub const SYS_OPEN_BY_HANDLE_AT: u32 = 304; -pub const SYS_CLOCK_ADJTIME: u32 = 305; -pub const SYS_SYNCFS: u32 = 306; -pub const SYS_SENDMMSG: u32 = 307; -pub const SYS_SETNS: u32 = 308; -pub const SYS_GETCPU: u32 = 309; -pub const SYS_PROCESS_VM_READV: u32 = 310; -pub const SYS_PROCESS_VM_WRITEV: u32 = 311; -pub const SYS_KCMP: u32 = 312; -pub const SYS_FINIT_MODULE: u32 = 313; -pub const SYS_SCHED_SETATTR: u32 = 314; -pub const SYS_SCHED_GETATTR: u32 = 315; -pub const SYS_RENAMEAT2: u32 = 316; -pub const SYS_SECCOMP: u32 = 317; -pub const SYS_GETRANDOM: u32 = 318; -pub const SYS_MEMFD_CREATE: u32 = 319; -pub const SYS_KEXEC_FILE_LOAD: u32 = 320; -pub const SYS_BPF: u32 = 321; -pub const SYS_EXECVEAT: u32 = 322; -pub const SYS_USERFAULTFD: u32 = 323; -pub const SYS_MEMBARRIER: u32 = 324; -pub const SYS_MLOCK2: u32 = 325; - -pub const SYS_SPAWN: u32 = 360; diff --git a/src/libos/src/syscall/mod.rs b/src/libos/src/syscall/mod.rs index 0bd8fd79..e93e85b6 100644 --- a/src/libos/src/syscall/mod.rs +++ b/src/libos/src/syscall/mod.rs @@ -6,32 +6,30 @@ //! 2. Do some bound checks then call `dispatch_syscall` (at this file) //! 3. Dispatch the syscall to `do_*` (at this file) //! 4. Do some memory checks then call `mod::do_*` (at each module) +pub use self::syscall_num::SyscallNum; use fs::{File, FileDesc, FileRef, Stat}; use misc::{resource_t, rlimit_t, utsname_t}; use net::{msghdr, msghdr_mut, AsSocket, AsUnixSocket, SocketFile, UnixSocketFile}; use process::{pid_t, ChildProcessFilter, CloneFlags, CpuSet, FileAction, FutexFlags, FutexOp}; +use std::any::Any; +use std::convert::TryFrom; use std::ffi::{CStr, CString}; +use std::io::{Read, Seek, SeekFrom, Write}; use std::ptr; -use time::{clockid_t, timespec_t, timeval_t}; +use time::{clockid_t, timespec_t, timeval_t, GLOBAL_PROFILER}; use util::mem_util::from_user::*; use vm::{MMapFlags, VMPerms}; use {fs, process, std, vm}; use super::*; -use self::consts::*; -use std::any::Any; -use std::io::{Read, Seek, SeekFrom, Write}; +mod syscall_num; // Use the internal syscall wrappers from sgx_tstd //use std::libc_fs as fs; //use std::libc_io as io; -mod consts; - -static mut SYSCALL_TIMING: [usize; 361] = [0; 361]; - #[no_mangle] #[deny(unreachable_patterns)] pub extern "C" fn dispatch_syscall( @@ -43,167 +41,159 @@ pub extern "C" fn dispatch_syscall( arg4: isize, arg5: isize, ) -> isize { - debug!( - "syscall tid:{}, num:{}: {:#x}, {:#x}, {:#x}, {:#x}, {:#x}, {:#x}", - process::do_gettid(), - num, - arg0, - arg1, - arg2, - arg3, - arg4, - arg5 - ); - #[cfg(feature = "syscall_timing")] - let time_start = { - static mut LAST_PRINT: usize = 0; - let time = crate::time::do_gettimeofday().as_usec(); - unsafe { - if time / 1000000 / 5 > LAST_PRINT { - LAST_PRINT = time / 1000000 / 5; - print_syscall_timing(); - } - } - time - }; + let pid = process::do_gettid(); + let syscall_num = SyscallNum::try_from(num).unwrap(); - let ret = match num { + debug!( + "syscall tid:{}, {:?}: {:#x}, {:#x}, {:#x}, {:#x}, {:#x}, {:#x}", + pid, syscall_num, arg0, arg1, arg2, arg3, arg4, arg5 + ); + + #[cfg(feature = "syscall_timing")] + GLOBAL_PROFILER + .lock() + .unwrap() + .syscall_enter(syscall_num) + .expect("unexpected error from profiler to enter syscall"); + + use self::syscall_num::SyscallNum::*; + let ret = match syscall_num { // file - SYS_OPEN => fs::do_open(arg0 as *const i8, arg1 as u32, arg2 as u32), - SYS_CLOSE => fs::do_close(arg0 as FileDesc), - SYS_READ => fs::do_read(arg0 as FileDesc, arg1 as *mut u8, arg2 as usize), - SYS_WRITE => fs::do_write(arg0 as FileDesc, arg1 as *const u8, arg2 as usize), - SYS_PREAD64 => fs::do_pread( + SysOpen => fs::do_open(arg0 as *const i8, arg1 as u32, arg2 as u32), + SysClose => fs::do_close(arg0 as FileDesc), + SysRead => fs::do_read(arg0 as FileDesc, arg1 as *mut u8, arg2 as usize), + SysWrite => fs::do_write(arg0 as FileDesc, arg1 as *const u8, arg2 as usize), + SysPread64 => fs::do_pread( arg0 as FileDesc, arg1 as *mut u8, arg2 as usize, arg3 as usize, ), - SYS_PWRITE64 => fs::do_pwrite( + SysPwrite64 => fs::do_pwrite( arg0 as FileDesc, arg1 as *const u8, arg2 as usize, arg3 as usize, ), - SYS_READV => fs::do_readv(arg0 as FileDesc, arg1 as *mut fs::iovec_t, arg2 as i32), - SYS_WRITEV => fs::do_writev(arg0 as FileDesc, arg1 as *mut fs::iovec_t, arg2 as i32), - SYS_STAT => fs::do_stat(arg0 as *const i8, arg1 as *mut Stat), - SYS_FSTAT => fs::do_fstat(arg0 as FileDesc, arg1 as *mut Stat), - SYS_LSTAT => fs::do_lstat(arg0 as *const i8, arg1 as *mut Stat), - SYS_ACCESS => fs::do_access(arg0 as *const i8, arg1 as u32), - SYS_FACCESSAT => fs::do_faccessat(arg0 as i32, arg1 as *const i8, arg2 as u32, arg3 as u32), - SYS_LSEEK => fs::do_lseek(arg0 as FileDesc, arg1 as off_t, arg2 as i32), - SYS_FSYNC => fs::do_fsync(arg0 as FileDesc), - SYS_FDATASYNC => fs::do_fdatasync(arg0 as FileDesc), - SYS_TRUNCATE => fs::do_truncate(arg0 as *const i8, arg1 as usize), - SYS_FTRUNCATE => fs::do_ftruncate(arg0 as FileDesc, arg1 as usize), - SYS_GETDENTS64 => fs::do_getdents64(arg0 as FileDesc, arg1 as *mut u8, arg2 as usize), - SYS_SYNC => fs::do_sync(), - SYS_GETCWD => do_getcwd(arg0 as *mut u8, arg1 as usize), - SYS_CHDIR => fs::do_chdir(arg0 as *mut i8), - SYS_RENAME => fs::do_rename(arg0 as *const i8, arg1 as *const i8), - SYS_MKDIR => fs::do_mkdir(arg0 as *const i8, arg1 as usize), - SYS_RMDIR => fs::do_rmdir(arg0 as *const i8), - SYS_LINK => fs::do_link(arg0 as *const i8, arg1 as *const i8), - SYS_UNLINK => fs::do_unlink(arg0 as *const i8), - SYS_READLINK => fs::do_readlink(arg0 as *const i8, arg1 as *mut u8, arg2 as usize), - SYS_SENDFILE => fs::do_sendfile( + SysReadv => fs::do_readv(arg0 as FileDesc, arg1 as *mut fs::iovec_t, arg2 as i32), + SysWritev => fs::do_writev(arg0 as FileDesc, arg1 as *mut fs::iovec_t, arg2 as i32), + SysStat => fs::do_stat(arg0 as *const i8, arg1 as *mut Stat), + SysFstat => fs::do_fstat(arg0 as FileDesc, arg1 as *mut Stat), + SysLstat => fs::do_lstat(arg0 as *const i8, arg1 as *mut Stat), + SysAccess => fs::do_access(arg0 as *const i8, arg1 as u32), + SysFaccessat => fs::do_faccessat(arg0 as i32, arg1 as *const i8, arg2 as u32, arg3 as u32), + SysLseek => fs::do_lseek(arg0 as FileDesc, arg1 as off_t, arg2 as i32), + SysFsync => fs::do_fsync(arg0 as FileDesc), + SysFdatasync => fs::do_fdatasync(arg0 as FileDesc), + SysTruncate => fs::do_truncate(arg0 as *const i8, arg1 as usize), + SysFtruncate => fs::do_ftruncate(arg0 as FileDesc, arg1 as usize), + SysGetdents64 => fs::do_getdents64(arg0 as FileDesc, arg1 as *mut u8, arg2 as usize), + SysSync => fs::do_sync(), + SysGetcwd => do_getcwd(arg0 as *mut u8, arg1 as usize), + SysChdir => fs::do_chdir(arg0 as *mut i8), + SysRename => fs::do_rename(arg0 as *const i8, arg1 as *const i8), + SysMkdir => fs::do_mkdir(arg0 as *const i8, arg1 as usize), + SysRmdir => fs::do_rmdir(arg0 as *const i8), + SysLink => fs::do_link(arg0 as *const i8, arg1 as *const i8), + SysUnlink => fs::do_unlink(arg0 as *const i8), + SysReadlink => fs::do_readlink(arg0 as *const i8, arg1 as *mut u8, arg2 as usize), + SysSendfile => fs::do_sendfile( arg0 as FileDesc, arg1 as FileDesc, arg2 as *mut off_t, arg3 as usize, ), - SYS_FCNTL => fs::do_fcntl(arg0 as FileDesc, arg1 as u32, arg2 as u64), - SYS_IOCTL => fs::do_ioctl(arg0 as FileDesc, arg1 as u32, arg2 as *mut u8), + SysFcntl => fs::do_fcntl(arg0 as FileDesc, arg1 as u32, arg2 as u64), + SysIoctl => fs::do_ioctl(arg0 as FileDesc, arg1 as u32, arg2 as *mut u8), - // IO multiplexing - SYS_SELECT => net::do_select( + // Io multiplexing + SysSelect => net::do_select( arg0 as c_int, arg1 as *mut libc::fd_set, arg2 as *mut libc::fd_set, arg3 as *mut libc::fd_set, arg4 as *const libc::timeval, ), - SYS_POLL => net::do_poll( + SysPoll => net::do_poll( arg0 as *mut libc::pollfd, arg1 as libc::nfds_t, arg2 as c_int, ), - SYS_EPOLL_CREATE => net::do_epoll_create(arg0 as c_int), - SYS_EPOLL_CREATE1 => net::do_epoll_create1(arg0 as c_int), - SYS_EPOLL_CTL => net::do_epoll_ctl( + SysEpollCreate => net::do_epoll_create(arg0 as c_int), + SysEpollCreate1 => net::do_epoll_create1(arg0 as c_int), + SysEpollCtl => net::do_epoll_ctl( arg0 as c_int, arg1 as c_int, arg2 as c_int, arg3 as *const libc::epoll_event, ), - SYS_EPOLL_WAIT => net::do_epoll_wait( + SysEpollWait => net::do_epoll_wait( arg0 as c_int, arg1 as *mut libc::epoll_event, arg2 as c_int, arg3 as c_int, ), - SYS_EPOLL_PWAIT => net::do_epoll_pwait( + SysEpollPwait => net::do_epoll_pwait( arg0 as c_int, arg1 as *mut libc::epoll_event, arg2 as c_int, arg3 as c_int, - arg4 as *const usize, //TODO:add sigset_t + arg4 as *const usize, //Todo:add sigset_t ), // process - SYS_EXIT => do_exit(arg0 as i32), - SYS_SPAWN => do_spawn( + SysExit => do_exit(arg0 as i32), + SysSpawn => do_spawn( arg0 as *mut u32, arg1 as *mut i8, arg2 as *const *const i8, arg3 as *const *const i8, arg4 as *const FdOp, ), - SYS_WAIT4 => do_wait4(arg0 as i32, arg1 as *mut i32), + SysWait4 => do_wait4(arg0 as i32, arg1 as *mut i32), - SYS_GETPID => do_getpid(), - SYS_GETTID => do_gettid(), - SYS_GETPPID => do_getppid(), - SYS_GETPGID => do_getpgid(), + SysGetpid => do_getpid(), + SysGettid => do_gettid(), + SysGetppid => do_getppid(), + SysGetpgid => do_getpgid(), - SYS_GETUID => do_getuid(), - SYS_GETGID => do_getgid(), - SYS_GETEUID => do_geteuid(), - SYS_GETEGID => do_getegid(), + SysGetuid => do_getuid(), + SysGetgid => do_getgid(), + SysGeteuid => do_geteuid(), + SysGetegid => do_getegid(), - SYS_RT_SIGACTION => do_rt_sigaction(), - SYS_RT_SIGPROCMASK => do_rt_sigprocmask(), + SysRtSigaction => do_rt_sigaction(), + SysRtSigprocmask => do_rt_sigprocmask(), - SYS_CLONE => do_clone( + SysClone => do_clone( arg0 as u32, arg1 as usize, arg2 as *mut pid_t, arg3 as *mut pid_t, arg4 as usize, ), - SYS_FUTEX => do_futex( + SysFutex => do_futex( arg0 as *const i32, arg1 as u32, arg2 as i32, arg3 as i32, arg4 as *const i32, - // TODO: accept other optional arguments + // Todo: accept other optional arguments ), - SYS_ARCH_PRCTL => do_arch_prctl(arg0 as u32, arg1 as *mut usize), - SYS_SET_TID_ADDRESS => do_set_tid_address(arg0 as *mut pid_t), + SysArchPrctl => do_arch_prctl(arg0 as u32, arg1 as *mut usize), + SysSetTidAddress => do_set_tid_address(arg0 as *mut pid_t), // sched - SYS_SCHED_YIELD => do_sched_yield(), - SYS_SCHED_GETAFFINITY => { + SysSchedYield => do_sched_yield(), + SysSchedGetaffinity => { do_sched_getaffinity(arg0 as pid_t, arg1 as size_t, arg2 as *mut c_uchar) } - SYS_SCHED_SETAFFINITY => { + SysSchedSetaffinity => { do_sched_setaffinity(arg0 as pid_t, arg1 as size_t, arg2 as *const c_uchar) } // memory - SYS_MMAP => do_mmap( + SysMmap => do_mmap( arg0 as usize, arg1 as usize, arg2 as i32, @@ -211,31 +201,31 @@ pub extern "C" fn dispatch_syscall( arg4 as FileDesc, arg5 as off_t, ), - SYS_MUNMAP => do_munmap(arg0 as usize, arg1 as usize), - SYS_MREMAP => do_mremap( + SysMunmap => do_munmap(arg0 as usize, arg1 as usize), + SysMremap => do_mremap( arg0 as usize, arg1 as usize, arg2 as usize, arg3 as i32, arg4 as usize, ), - SYS_MPROTECT => do_mprotect(arg0 as usize, arg1 as usize, arg2 as u32), - SYS_BRK => do_brk(arg0 as usize), + SysMprotect => do_mprotect(arg0 as usize, arg1 as usize, arg2 as u32), + SysBrk => do_brk(arg0 as usize), - SYS_PIPE => fs::do_pipe2(arg0 as *mut i32, 0), - SYS_PIPE2 => fs::do_pipe2(arg0 as *mut i32, arg1 as u32), - SYS_DUP => fs::do_dup(arg0 as FileDesc), - SYS_DUP2 => fs::do_dup2(arg0 as FileDesc, arg1 as FileDesc), - SYS_DUP3 => fs::do_dup3(arg0 as FileDesc, arg1 as FileDesc, arg2 as u32), + SysPipe => fs::do_pipe2(arg0 as *mut i32, 0), + SysPipe2 => fs::do_pipe2(arg0 as *mut i32, arg1 as u32), + SysDup => fs::do_dup(arg0 as FileDesc), + SysDup2 => fs::do_dup2(arg0 as FileDesc, arg1 as FileDesc), + SysDup3 => fs::do_dup3(arg0 as FileDesc, arg1 as FileDesc, arg2 as u32), - SYS_GETTIMEOFDAY => do_gettimeofday(arg0 as *mut timeval_t), - SYS_CLOCK_GETTIME => do_clock_gettime(arg0 as clockid_t, arg1 as *mut timespec_t), + SysGettimeofday => do_gettimeofday(arg0 as *mut timeval_t), + SysClockGettime => do_clock_gettime(arg0 as clockid_t, arg1 as *mut timespec_t), - SYS_NANOSLEEP => do_nanosleep(arg0 as *const timespec_t, arg1 as *mut timespec_t), + SysNanosleep => do_nanosleep(arg0 as *const timespec_t, arg1 as *mut timespec_t), - SYS_UNAME => do_uname(arg0 as *mut utsname_t), + SysUname => do_uname(arg0 as *mut utsname_t), - SYS_PRLIMIT64 => do_prlimit( + SysPrlimit64 => do_prlimit( arg0 as pid_t, arg1 as u32, arg2 as *const rlimit_t, @@ -243,56 +233,56 @@ pub extern "C" fn dispatch_syscall( ), // socket - SYS_SOCKET => do_socket(arg0 as c_int, arg1 as c_int, arg2 as c_int), - SYS_CONNECT => do_connect( + SysSocket => do_socket(arg0 as c_int, arg1 as c_int, arg2 as c_int), + SysConnect => do_connect( arg0 as c_int, arg1 as *const libc::sockaddr, arg2 as libc::socklen_t, ), - SYS_ACCEPT => do_accept4( + SysAccept => do_accept4( arg0 as c_int, arg1 as *mut libc::sockaddr, arg2 as *mut libc::socklen_t, 0, ), - SYS_ACCEPT4 => do_accept4( + SysAccept4 => do_accept4( arg0 as c_int, arg1 as *mut libc::sockaddr, arg2 as *mut libc::socklen_t, arg3 as c_int, ), - SYS_SHUTDOWN => do_shutdown(arg0 as c_int, arg1 as c_int), - SYS_BIND => do_bind( + SysShutdown => do_shutdown(arg0 as c_int, arg1 as c_int), + SysBind => do_bind( arg0 as c_int, arg1 as *const libc::sockaddr, arg2 as libc::socklen_t, ), - SYS_LISTEN => do_listen(arg0 as c_int, arg1 as c_int), - SYS_SETSOCKOPT => do_setsockopt( + SysListen => do_listen(arg0 as c_int, arg1 as c_int), + SysSetsockopt => do_setsockopt( arg0 as c_int, arg1 as c_int, arg2 as c_int, arg3 as *const c_void, arg4 as libc::socklen_t, ), - SYS_GETSOCKOPT => do_getsockopt( + SysGetsockopt => do_getsockopt( arg0 as c_int, arg1 as c_int, arg2 as c_int, arg3 as *mut c_void, arg4 as *mut libc::socklen_t, ), - SYS_GETPEERNAME => do_getpeername( + SysGetpeername => do_getpeername( arg0 as c_int, arg1 as *mut libc::sockaddr, arg2 as *mut libc::socklen_t, ), - SYS_GETSOCKNAME => do_getsockname( + SysGetsockname => do_getsockname( arg0 as c_int, arg1 as *mut libc::sockaddr, arg2 as *mut libc::socklen_t, ), - SYS_SENDTO => do_sendto( + SysSendto => do_sendto( arg0 as c_int, arg1 as *const c_void, arg2 as size_t, @@ -300,7 +290,7 @@ pub extern "C" fn dispatch_syscall( arg4 as *const libc::sockaddr, arg5 as libc::socklen_t, ), - SYS_RECVFROM => do_recvfrom( + SysRecvfrom => do_recvfrom( arg0 as c_int, arg1 as *mut c_void, arg2 as size_t, @@ -309,29 +299,27 @@ pub extern "C" fn dispatch_syscall( arg5 as *mut libc::socklen_t, ), - SYS_SOCKETPAIR => do_socketpair( + SysSocketpair => do_socketpair( arg0 as c_int, arg1 as c_int, arg2 as c_int, arg3 as *mut c_int, ), - SYS_SENDMSG => net::do_sendmsg(arg0 as c_int, arg1 as *const msghdr, arg2 as c_int), - SYS_RECVMSG => net::do_recvmsg(arg0 as c_int, arg1 as *mut msghdr_mut, arg2 as c_int), + SysSendmsg => net::do_sendmsg(arg0 as c_int, arg1 as *const msghdr, arg2 as c_int), + SysRecvmsg => net::do_recvmsg(arg0 as c_int, arg1 as *mut msghdr_mut, arg2 as c_int), _ => do_unknown(num, arg0, arg1, arg2, arg3, arg4, arg5), }; #[cfg(feature = "syscall_timing")] - { - let time_end = crate::time::do_gettimeofday().as_usec(); - let time = time_end - time_start; - unsafe { - SYSCALL_TIMING[num as usize] += time as usize; - } - } + GLOBAL_PROFILER + .lock() + .unwrap() + .syscall_exit(syscall_num, ret.is_err()) + .expect("unexpected error from profiler to exit syscall"); - info!("=> {:?}", ret); + info!("tid: {} => {:?} ", process::do_gettid(), ret); match ret { Ok(retval) => retval as isize, @@ -345,20 +333,6 @@ pub extern "C" fn dispatch_syscall( } } -#[cfg(feature = "syscall_timing")] -fn print_syscall_timing() { - println!("syscall timing:"); - for (i, &time) in unsafe { SYSCALL_TIMING }.iter().enumerate() { - if time == 0 { - continue; - } - println!("{:>3}: {:>6} us", i, time); - } - for x in unsafe { SYSCALL_TIMING.iter_mut() } { - *x = 0; - } -} - /* * This Rust-version of fdop correspond to the C-version one in Occlum. * See /src/process/fdop.h. diff --git a/src/libos/src/syscall/syscall_num.rs b/src/libos/src/syscall/syscall_num.rs new file mode 100644 index 00000000..e42e9567 --- /dev/null +++ b/src/libos/src/syscall/syscall_num.rs @@ -0,0 +1,345 @@ +use super::*; + +#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] +pub enum SyscallNum { + SysRead = 0, + SysWrite = 1, + SysOpen = 2, + SysClose = 3, + SysStat = 4, + SysFstat = 5, + SysLstat = 6, + SysPoll = 7, + SysLseek = 8, + SysMmap = 9, + SysMprotect = 10, + SysMunmap = 11, + SysBrk = 12, + SysRtSigaction = 13, + SysRtSigprocmask = 14, + SysRtSigreturn = 15, + SysIoctl = 16, + SysPread64 = 17, + SysPwrite64 = 18, + SysReadv = 19, + SysWritev = 20, + SysAccess = 21, + SysPipe = 22, + SysSelect = 23, + SysSchedYield = 24, + SysMremap = 25, + SysMsync = 26, + SysMincore = 27, + SysMadvise = 28, + SysShmget = 29, + SysShmat = 30, + SysShmctl = 31, + SysDup = 32, + SysDup2 = 33, + SysPause = 34, + SysNanosleep = 35, + SysGetitimer = 36, + SysAlarm = 37, + SysSetitimer = 38, + SysGetpid = 39, + SysSendfile = 40, + SysSocket = 41, + SysConnect = 42, + SysAccept = 43, + SysSendto = 44, + SysRecvfrom = 45, + SysSendmsg = 46, + SysRecvmsg = 47, + SysShutdown = 48, + SysBind = 49, + SysListen = 50, + SysGetsockname = 51, + SysGetpeername = 52, + SysSocketpair = 53, + SysSetsockopt = 54, + SysGetsockopt = 55, + SysClone = 56, + SysFork = 57, + SysVfork = 58, + SysExecve = 59, + SysExit = 60, + SysWait4 = 61, + SysKill = 62, + SysUname = 63, + SysSemget = 64, + SysSemop = 65, + SysSemctl = 66, + SysShmdt = 67, + SysMsgget = 68, + SysMsgsnd = 69, + SysMsgrcv = 70, + SysMsgctl = 71, + SysFcntl = 72, + SysFlock = 73, + SysFsync = 74, + SysFdatasync = 75, + SysTruncate = 76, + SysFtruncate = 77, + SysGetdents = 78, + SysGetcwd = 79, + SysChdir = 80, + SysFchdir = 81, + SysRename = 82, + SysMkdir = 83, + SysRmdir = 84, + SysCreat = 85, + SysLink = 86, + SysUnlink = 87, + SysSymlink = 88, + SysReadlink = 89, + SysChmod = 90, + SysFchmod = 91, + SysChown = 92, + SysFchown = 93, + SysLchown = 94, + SysUmask = 95, + SysGettimeofday = 96, + SysGetrlimit = 97, + SysGetrusage = 98, + SysSysInfo = 99, + SysTimes = 100, + SysPtrace = 101, + SysGetuid = 102, + SysSysLog = 103, + SysGetgid = 104, + SysSetuid = 105, + SysSetgid = 106, + SysGeteuid = 107, + SysGetegid = 108, + SysSetpgid = 109, + SysGetppid = 110, + SysGetpgrp = 111, + SysSetsid = 112, + SysSetreuid = 113, + SysSetregid = 114, + SysGetgroups = 115, + SysSetgroups = 116, + SysSetresuid = 117, + SysGetresuid = 118, + SysSetresgid = 119, + SysGetresgid = 120, + SysGetpgid = 121, + SysSetfsuid = 122, + SysSetfsgid = 123, + SysGetsid = 124, + SysCapget = 125, + SysCapset = 126, + SysRtSigpending = 127, + SysRtSigtimedwait = 128, + SysRtSigqueueinfo = 129, + SysRtSigsuspend = 130, + SysSigaltstack = 131, + SysUtime = 132, + SysMknod = 133, + SysUselib = 134, + SysPersonality = 135, + SysUstat = 136, + SysStatfs = 137, + SysFstatfs = 138, + SysSysFs = 139, + SysGetpriority = 140, + SysSetpriority = 141, + SysSchedSetparam = 142, + SysSchedGetparam = 143, + SysSchedSetscheduler = 144, + SysSchedGetscheduler = 145, + SysSchedGetPriorityMax = 146, + SysSchedGetPriorityMin = 147, + SysSchedRrGetInterval = 148, + SysMlock = 149, + SysMunlock = 150, + SysMlockall = 151, + SysMunlockall = 152, + SysVhangup = 153, + SysModifyLdt = 154, + SysPivotRoot = 155, + SysSysCtl = 156, + SysPrctl = 157, + SysArchPrctl = 158, + SysAdjtimex = 159, + SysSetrlimit = 160, + SysChroot = 161, + SysSync = 162, + SysAcct = 163, + SysSettimeofday = 164, + SysMount = 165, + SysUmount2 = 166, + SysSwapon = 167, + SysSwapoff = 168, + SysReboot = 169, + SysSethostname = 170, + SysSetdomainname = 171, + SysIopl = 172, + SysIoperm = 173, + SysCreateModule = 174, + SysInitModule = 175, + SysDeleteModule = 176, + SysGetKernelSyms = 177, + SysQueryModule = 178, + SysQuotactl = 179, + SysNfsservctl = 180, + SysGetpmsg = 181, + SysPutpmsg = 182, + SysAfsSysCall = 183, + SysTuxcall = 184, + SysSecurity = 185, + SysGettid = 186, + SysReadahead = 187, + SysSetxattr = 188, + SysLsetxattr = 189, + SysFsetxattr = 190, + SysGetxattr = 191, + SysLgetxattr = 192, + SysFgetxattr = 193, + SysListxattr = 194, + SysLlistxattr = 195, + SysFlistxattr = 196, + SysRemovexattr = 197, + SysLremovexattr = 198, + SysFremovexattr = 199, + SysTkill = 200, + SysTime = 201, + SysFutex = 202, + SysSchedSetaffinity = 203, + SysSchedGetaffinity = 204, + SysSetThreadArea = 205, + SysIoSetup = 206, + SysIoDestroy = 207, + SysIoGetevents = 208, + SysIoSubmit = 209, + SysIoCancel = 210, + SysGetThreadArea = 211, + SysLookupDcookie = 212, + SysEpollCreate = 213, + SysEpollCtlOld = 214, + SysEpollWaitOld = 215, + SysRemapFilePages = 216, + SysGetdents64 = 217, + SysSetTidAddress = 218, + SysRestartSysCall = 219, + SysSemtimedop = 220, + SysFadvise64 = 221, + SysTimerCreate = 222, + SysTimerSettime = 223, + SysTimerGettime = 224, + SysTimerGetoverrun = 225, + SysTimerDelete = 226, + SysClockSettime = 227, + SysClockGettime = 228, + SysClockGetres = 229, + SysClockNanosleep = 230, + SysExitGroup = 231, + SysEpollWait = 232, + SysEpollCtl = 233, + SysTgkill = 234, + SysUtimes = 235, + SysVserver = 236, + SysMbind = 237, + SysSetMempolicy = 238, + SysGetMempolicy = 239, + SysMqOpen = 240, + SysMqUnlink = 241, + SysMqTimedsend = 242, + SysMqTimedreceive = 243, + SysMqNotify = 244, + SysMqGetsetattr = 245, + SysKexecLoad = 246, + SysWaitid = 247, + SysAddKey = 248, + SysRequestKey = 249, + SysKeyctl = 250, + SysIoprioSet = 251, + SysIoprioGet = 252, + SysInotifyInit = 253, + SysInotifyAddWatch = 254, + SysInotifyRmWatch = 255, + SysMigratePages = 256, + SysOpenat = 257, + SysMkdirat = 258, + SysMknodat = 259, + SysFchownat = 260, + SysFutimesat = 261, + SysNewfstatat = 262, + SysUnlinkat = 263, + SysRenameat = 264, + SysLinkat = 265, + SysSymlinkat = 266, + SysReadlinkat = 267, + SysFchmodat = 268, + SysFaccessat = 269, + SysPselect6 = 270, + SysPpoll = 271, + SysUnshare = 272, + SysSetRobustList = 273, + SysGetRobustList = 274, + SysSplice = 275, + SysTee = 276, + SysSyncFileRange = 277, + SysVmsplice = 278, + SysMovePages = 279, + SysUtimensat = 280, + SysEpollPwait = 281, + SysSignalfd = 282, + SysTimerfdCreate = 283, + SysEventfd = 284, + SysFallocate = 285, + SysTimerfdSettime = 286, + SysTimerfdGettime = 287, + SysAccept4 = 288, + SysSignalfd4 = 289, + SysEventfd2 = 290, + SysEpollCreate1 = 291, + SysDup3 = 292, + SysPipe2 = 293, + SysInotifyInit1 = 294, + SysPreadv = 295, + SysPwritev = 296, + SysRtTgsigqueueinfo = 297, + SysPerfEventOpen = 298, + SysRecvmmsg = 299, + SysFanotifyInit = 300, + SysFanotifyMark = 301, + SysPrlimit64 = 302, + SysNameToHandleAt = 303, + SysOpenByHandleAt = 304, + SysClockAdjtime = 305, + SysSyncfs = 306, + SysSendmmsg = 307, + SysSetns = 308, + SysGetcpu = 309, + SysProcessVmReadv = 310, + SysProcessVmWritev = 311, + SysKcmp = 312, + SysFinitModule = 313, + SysSchedSetattr = 314, + SysSchedGetattr = 315, + SysRenameat2 = 316, + SysSeccomp = 317, + SysGetrandom = 318, + SysMemfdCreate = 319, + SysKexecFileLoad = 320, + SysBpf = 321, + SysExecveat = 322, + SysUserfaultfd = 323, + SysMembarrier = 324, + SysMlock2 = 325, + + SysSpawn = 360, +} + +impl TryFrom for SyscallNum { + type Error = error::Error; + + fn try_from(value: u32) -> Result { + if value > 325 && value != 360 { + return_errno!(EINVAL, "invalid syscall number"); + } else { + Ok(unsafe { core::mem::transmute(value as u16) }) + } + } +} diff --git a/src/libos/src/time/mod.rs b/src/libos/src/time/mod.rs index de172c92..e3d06a0a 100644 --- a/src/libos/src/time/mod.rs +++ b/src/libos/src/time/mod.rs @@ -1,7 +1,15 @@ +use super::*; +use core::convert::TryFrom; +use process::pid_t; use rcore_fs::dev::TimeProvider; use rcore_fs::vfs::Timespec; +use std::time::Duration; +use std::{fmt, u64}; +use syscall::SyscallNum; -use super::*; +mod profiler; + +pub use profiler::GLOBAL_PROFILER; #[allow(non_camel_case_types)] pub type time_t = i64; @@ -18,10 +26,6 @@ pub struct timeval_t { } impl timeval_t { - pub fn as_usec(&self) -> usize { - (self.sec * 1000000 + self.usec) as usize - } - pub fn validate(&self) -> Result<()> { if self.sec >= 0 && self.usec >= 0 && self.usec < 1_000_000 { Ok(()) @@ -29,6 +33,10 @@ impl timeval_t { return_errno!(EINVAL, "invalid value for timeval_t"); } } + + pub fn as_duration(&self) -> Duration { + Duration::new(self.sec as u64, (self.usec * 1_000) as u32) + } } pub fn do_gettimeofday() -> timeval_t { @@ -55,9 +63,7 @@ pub struct timespec_t { impl timespec_t { pub fn from_raw_ptr(ptr: *const timespec_t) -> Result { let ts = unsafe { *ptr }; - if ts.sec < 0 || ts.nsec < 0 || ts.nsec >= 1_000_000_000 { - return_errno!(EINVAL, "Invalid timespec fields"); - } + ts.validate()?; Ok(ts) } @@ -68,6 +74,10 @@ impl timespec_t { return_errno!(EINVAL, "invalid value for timespec_t"); } } + + pub fn as_duration(&self) -> Duration { + Duration::new(self.sec as u64, self.nsec as u32) + } } #[allow(non_camel_case_types)] @@ -126,6 +136,22 @@ pub fn do_nanosleep(req: ×pec_t) -> Result<()> { Ok(()) } +pub fn do_thread_getcpuclock() -> Result { + extern "C" { + fn occlum_ocall_thread_getcpuclock(ret: *mut c_int, tp: *mut timespec_t) -> sgx_status_t; + } + + let mut tv: timespec_t = Default::default(); + try_libc!({ + let mut retval: i32 = 0; + let status = occlum_ocall_thread_getcpuclock(&mut retval, &mut tv as *mut timespec_t); + assert!(status == sgx_status_t::SGX_SUCCESS); + retval + }); + tv.validate()?; + Ok(tv) +} + // For SEFS pub struct OcclumTimeProvider; diff --git a/src/libos/src/time/profiler.rs b/src/libos/src/time/profiler.rs new file mode 100644 index 00000000..452c5752 --- /dev/null +++ b/src/libos/src/time/profiler.rs @@ -0,0 +1,395 @@ +use super::*; + +lazy_static! { + pub static ref GLOBAL_PROFILER: SgxMutex = SgxMutex::new(GlobalProfiler::new()); +} + +/// A profiler that can be used across threads. +// TODO: Use light-weight thread_local storage other than mutex +pub struct GlobalProfiler { + inner: HashMap, +} + +impl GlobalProfiler { + pub fn new() -> Self { + Self { + inner: HashMap::new(), + } + } + + pub fn thread_enter(&mut self) -> Result<()> { + let tid = process::do_gettid(); + if self.inner.insert(tid, ThreadProfiler::new()).is_some() { + return_errno!( + EINVAL, + "global profiler should exit the thread before entering" + ); + } + self.inner.get_mut(&tid).unwrap().start() + } + + pub fn thread_exit(&mut self) -> Result<()> { + // A thread exits by invoking SysExit syscall which + // will never return + self.syscall_exit(SyscallNum::SysExit, false); + + let tid = process::do_gettid(); + println!("thread {} exits", tid); + + let mut exiting_profiler = self.inner.remove(&tid).ok_or_else(|| { + errno!( + EINVAL, + "global profiler should enter a thread before exit one" + ) + })?; + exiting_profiler.stop()?; + exiting_profiler.display()?; + Ok(()) + } + + pub fn syscall_enter(&mut self, syscall_num: SyscallNum) -> Result<()> { + let tid = process::do_gettid(); + let mut prof = self.inner.get_mut(&tid).unwrap(); + prof.syscall_enter(syscall_num) + } + + pub fn syscall_exit(&mut self, syscall_num: SyscallNum, is_err: bool) -> Result<()> { + let tid = process::do_gettid(); + let mut prof = self.inner.get_mut(&tid).unwrap(); + prof.syscall_exit(syscall_num, is_err) + } +} +/// A profiler used inside a thread. +// TODO: add support for exception +#[derive(Clone)] +pub struct ThreadProfiler { + syscall_data: HashMap, + start_time: ProfileTime, + status: Status, +} + +impl ThreadProfiler { + pub fn new() -> Self { + Self { + syscall_data: HashMap::new(), + start_time: ProfileTime::TwoTimes { + real: Duration::new(0, 0), + cpu: Duration::new(0, 0), + }, + status: Status::Stopped(TimeSummary::new( + Duration::new(0, 0), + Duration::new(0, 0), + Duration::new(0, 0), + )), + } + } + + fn start(&mut self) -> Result<()> { + match self.status { + Status::Stopped(..) => { + self.status = Status::Running; + self.start_time.update() + } + _ => return_errno!( + EINVAL, + "thread profiler can only be started in stopped status" + ), + } + } + + fn stop(&mut self) -> Result<()> { + if self.status != Status::Running { + error!("wrong status is {:?}", self.status); + return_errno!(EINVAL, "fail to stop thread profiler"); + } + let real = time::do_gettimeofday().as_duration() - self.start_time.get_realtime().unwrap(); + + let total_cputime = + time::do_thread_getcpuclock()?.as_duration() - self.start_time.get_cputime().unwrap(); + let sys = self.get_syscall_total_time()?; + let usr = total_cputime - sys; + self.status = Status::Stopped(TimeSummary::new(real, usr, sys)); + Ok(()) + } + + fn syscall_enter(&mut self, syscall_num: SyscallNum) -> Result<()> { + match self.status { + Status::Running => { + let mut cur_time = ProfileTime::CpuTime(Default::default()); + cur_time.update()?; + self.status = Status::InSyscall { + start_cpu: cur_time, + num: syscall_num, + }; + self.syscall_data + .entry(syscall_num) + .or_insert(PerfEntry::new()); + Ok(()) + } + _ => return_errno!( + EINVAL, + "threa profiler should be started before entering syscall" + ), + } + } + + fn syscall_exit(&mut self, syscall_num: SyscallNum, is_err: bool) -> Result<()> { + match self.status { + Status::InSyscall { start_cpu, num } => { + if syscall_num != num { + return_errno!(EINVAL, "syscall number mismatches"); + } + self.status = Status::Running; + let syscall_cpu_time = + time::do_thread_getcpuclock()?.as_duration() - start_cpu.get_cputime().unwrap(); + + self.syscall_data.entry(num).and_modify(|e| { + e.update(syscall_cpu_time, is_err) + .expect("fail to update syscall data") + }); + Ok(()) + } + _ => return_errno!( + EINVAL, + "thread profiler should be in one syscall before exiting the syscall" + ), + } + } + + fn get_syscall_total_time(&self) -> Result { + Ok(self.get_syscall_total()?.0) + } + + fn get_syscall_total(&self) -> Result<(Duration, u32, u32)> { + let mut total_time: Duration = Duration::new(0, 0); + let mut total_calls: u32 = 0; + let mut total_errors: u32 = 0; + for entry in self.syscall_data.values() { + total_time += entry.get_total_time(); + total_calls = entry + .get_calls() + .checked_add(total_calls) + .ok_or_else(|| errno!(EOVERFLOW, "total calls overflow"))?; + total_errors += entry.get_errors(); + } + Ok((total_time, total_calls, total_errors)) + } + + fn display(&self) -> Result<()> { + match self.status { + Status::Stopped(report) => { + // Pretty-print the Debug formatting report of the profiled thread + println!("{:#?}", report); + // Print the syscall statistics of the profiled thread + self.display_syscall_stat() + } + _ => return_errno!(EINVAL, "thread profiler can report only in stopped status"), + } + } + + /// Print the syscall statistics of the profiled thread. + /// + /// The statistics consist of: + /// syscall number, the corresponding percentage of the aggregate time in all the syscalls, + /// the aggregate time, average execution time of a call, aggregate calls, aggregate errors, + /// the shortest and longest execution time of the syscall. + /// A piece of the output is: + /// syscall % time seconds us/call calls errors range(us) + /// ------------------- ------ ----------- ----------- --------- --------- ----------- + /// SysWritev 0.40 0.000131 26 5 0 [12, 47] + /// SysMprotect 0.03 0.000009 4 2 0 [4, 4] + /// ------------------- ------ ----------- ----------- --------- --------- ----------- + fn display_syscall_stat(&self) -> Result<()> { + println!( + "{:<19} {:>6} {:>11} {:>11} {:>9} {:>9} {}", + "syscall", "% time", "seconds", "us/call", "calls", "errors", "range(us)", + ); + println!( + "{:-<19} {:-<6} {:-<11} {:-<11} {:-<9} {:-<9} {:-<11}", + "", "", "", "", "", "", "" + ); + + let (total_time, total_calls, total_errors) = self.get_syscall_total()?; + let mut syscall_data_ref: Vec<(&SyscallNum, &PerfEntry)> = + self.syscall_data.iter().collect(); + syscall_data_ref.sort_by(|(_, entry_a), (_, entry_b)| { + entry_b.get_total_time().cmp(&(entry_a.get_total_time())) + }); + + for (syscall_num, entry) in syscall_data_ref { + let time_percentage = + entry.get_total_time().as_secs_f64() / total_time.as_secs_f64() * 100_f64; + println!( + "{:<19} {:>6.2} {:?}", + format!("{:?}", syscall_num), + time_percentage, + entry, + ); + } + + println!( + "{:-<19} {:-<6} {:-<11} {:-<11} {:-<9} {:-<9} {:-<11}", + "", "", "", "", "", "", "" + ); + + println!( + "{} {:>20} {:>11.6} {:>21} {:>9}", + "total", + "100", + total_time.as_secs_f64(), + total_calls, + total_errors, + ); + Ok(()) + } +} + +#[derive(Copy, Clone)] +struct PerfEntry { + calls: u32, + total_time: Duration, + peak: Duration, + bottom: Duration, + errors: u32, +} + +impl PerfEntry { + fn new() -> Self { + Self { + calls: 0, + total_time: Duration::new(0, 0), + peak: Duration::new(0, 0), + bottom: Duration::new(u64::MAX, 1_000_000_000 - 1), + errors: 0, + } + } + + fn update(&mut self, time: Duration, is_err: bool) -> Result<()> { + self.calls = self + .calls + .checked_add(1) + .ok_or_else(|| errno!(EOVERFLOW, "single syscallduration addition overflow"))?; + self.total_time += time; + + if time > self.peak { + self.peak = time; + } + + if time < self.bottom { + self.bottom = time; + } + + if is_err { + self.errors += 1; + } + Ok(()) + } + + fn get_average(&self) -> Duration { + if self.calls == 0 { + Duration::new(0, 0) + } else { + self.total_time / self.calls + } + } + + fn get_calls(&self) -> u32 { + self.calls + } + + fn get_total_time(&self) -> Duration { + self.total_time + } + + fn get_errors(&self) -> u32 { + self.errors + } +} + +/// Used for the display of ThreadProfiler. +/// The total execution time in secs, average execution time in microseconds, +/// total calls, total errors, the shortest and longest execution time. +/// The output looks like: +/// 0.000009 4 2 0 [4, 4] +impl fmt::Debug for PerfEntry { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{:>11.6} {:>11} {:>9} {:>9} [{}, {}]", + self.total_time.as_secs_f64(), + self.get_average().as_micros(), + self.calls, + self.errors, + self.bottom.as_micros(), + self.peak.as_micros() + ) + } +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +enum ProfileTime { + RealTime(Duration), + CpuTime(Duration), + TwoTimes { real: Duration, cpu: Duration }, +} + +impl ProfileTime { + fn get_realtime(&self) -> Option { + match *self { + ProfileTime::RealTime(t) => Some(t), + ProfileTime::CpuTime(t) => None, + ProfileTime::TwoTimes { real, cpu } => Some(real), + } + } + + fn get_cputime(&self) -> Option { + match *self { + ProfileTime::RealTime(t) => None, + ProfileTime::CpuTime(t) => Some(t), + ProfileTime::TwoTimes { real, cpu } => Some(cpu), + } + } + + fn update(&mut self) -> Result<()> { + match self { + ProfileTime::RealTime(ref mut t) => *t = time::do_gettimeofday().as_duration(), + ProfileTime::CpuTime(ref mut t) => *t = time::do_thread_getcpuclock()?.as_duration(), + ProfileTime::TwoTimes { + ref mut real, + ref mut cpu, + } => { + *real = time::do_gettimeofday().as_duration(); + *cpu = time::do_thread_getcpuclock()?.as_duration(); + } + } + Ok(()) + } +} + +/// The timing statistics about one thread. +/// These statistics consist of: +/// (i) the elapsed real time between invocation and termination +/// (ii) the CPU time running in user space +/// (iii) the CPU time running in libos +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +struct TimeSummary { + real: Duration, + usr: Duration, + sys: Duration, +} + +impl TimeSummary { + fn new(real: Duration, usr: Duration, sys: Duration) -> Self { + Self { real, usr, sys } + } +} + +#[derive(Clone, Debug, Eq, PartialEq)] +enum Status { + Running, + Stopped(TimeSummary), + InSyscall { + start_cpu: ProfileTime, + num: SyscallNum, + }, +} diff --git a/src/pal/src/ocalls/time.c b/src/pal/src/ocalls/time.c index 61cc7154..88481b81 100644 --- a/src/pal/src/ocalls/time.c +++ b/src/pal/src/ocalls/time.c @@ -1,3 +1,4 @@ +#include #include #include "ocalls.h" @@ -12,3 +13,14 @@ void occlum_ocall_clock_gettime(int clockid, struct timespec *tp) { void occlum_ocall_nanosleep(const struct timespec* req) { nanosleep(req, NULL); } + +int occlum_ocall_thread_getcpuclock(struct timespec *tp) { + clockid_t thread_clock_id; + int ret = pthread_getcpuclockid(pthread_self(), &thread_clock_id); + if(ret != 0) { + PAL_ERROR("failed to get clock id"); + return -1; + } + + return clock_gettime(thread_clock_id, tp); +}