Add performance profiler for threads and system calls
This commit is contained in:
		
							parent
							
								
									a1e003ebdb
								
							
						
					
					
						commit
						74fad28938
					
				| @ -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); | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -98,11 +98,25 @@ pub fn run_task(libos_tid: pid_t, host_tid: pid_t) -> Result<i32> { | ||||
|         (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(); | ||||
|  | ||||
| @ -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; | ||||
| @ -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 <path_to_musl_libc>/src/process/fdop.h. | ||||
|  | ||||
							
								
								
									
										345
									
								
								src/libos/src/syscall/syscall_num.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										345
									
								
								src/libos/src/syscall/syscall_num.rs
									
									
									
									
									
										Normal file
									
								
							| @ -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<u32> for SyscallNum { | ||||
|     type Error = error::Error; | ||||
| 
 | ||||
|     fn try_from(value: u32) -> Result<Self> { | ||||
|         if value > 325 && value != 360 { | ||||
|             return_errno!(EINVAL, "invalid syscall number"); | ||||
|         } else { | ||||
|             Ok(unsafe { core::mem::transmute(value as u16) }) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -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<timespec_t> { | ||||
|         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<timespec_t> { | ||||
|     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; | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										395
									
								
								src/libos/src/time/profiler.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										395
									
								
								src/libos/src/time/profiler.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,395 @@ | ||||
| use super::*; | ||||
| 
 | ||||
| lazy_static! { | ||||
|     pub static ref GLOBAL_PROFILER: SgxMutex<GlobalProfiler> = 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<pid_t, ThreadProfiler>, | ||||
| } | ||||
| 
 | ||||
| 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<SyscallNum, PerfEntry>, | ||||
|     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<Duration> { | ||||
|         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<Duration> { | ||||
|         match *self { | ||||
|             ProfileTime::RealTime(t) => Some(t), | ||||
|             ProfileTime::CpuTime(t) => None, | ||||
|             ProfileTime::TwoTimes { real, cpu } => Some(real), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn get_cputime(&self) -> Option<Duration> { | ||||
|         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, | ||||
|     }, | ||||
| } | ||||
| @ -1,3 +1,4 @@ | ||||
| #include <pthread.h> | ||||
| #include <sys/time.h> | ||||
| #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); | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user