github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/syscalls/linux/sys_rusage.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package linux 16 17 import ( 18 "github.com/SagerNet/gvisor/pkg/abi/linux" 19 "github.com/SagerNet/gvisor/pkg/errors/linuxerr" 20 "github.com/SagerNet/gvisor/pkg/sentry/arch" 21 "github.com/SagerNet/gvisor/pkg/sentry/kernel" 22 ktime "github.com/SagerNet/gvisor/pkg/sentry/kernel/time" 23 "github.com/SagerNet/gvisor/pkg/sentry/usage" 24 ) 25 26 func getrusage(t *kernel.Task, which int32) linux.Rusage { 27 var cs usage.CPUStats 28 29 switch which { 30 case linux.RUSAGE_SELF: 31 cs = t.ThreadGroup().CPUStats() 32 33 case linux.RUSAGE_CHILDREN: 34 cs = t.ThreadGroup().JoinedChildCPUStats() 35 36 case linux.RUSAGE_THREAD: 37 cs = t.CPUStats() 38 39 case linux.RUSAGE_BOTH: 40 tg := t.ThreadGroup() 41 cs = tg.CPUStats() 42 cs.Accumulate(tg.JoinedChildCPUStats()) 43 } 44 45 return linux.Rusage{ 46 UTime: linux.NsecToTimeval(cs.UserTime.Nanoseconds()), 47 STime: linux.NsecToTimeval(cs.SysTime.Nanoseconds()), 48 NVCSw: int64(cs.VoluntarySwitches), 49 MaxRSS: int64(t.MaxRSS(which) / 1024), 50 } 51 } 52 53 // Getrusage implements linux syscall getrusage(2). 54 // marked "y" are supported now 55 // marked "*" are not used on Linux 56 // marked "p" are pending for support 57 // 58 // y struct timeval ru_utime; /* user CPU time used */ 59 // y struct timeval ru_stime; /* system CPU time used */ 60 // p long ru_maxrss; /* maximum resident set size */ 61 // * long ru_ixrss; /* integral shared memory size */ 62 // * long ru_idrss; /* integral unshared data size */ 63 // * long ru_isrss; /* integral unshared stack size */ 64 // p long ru_minflt; /* page reclaims (soft page faults) */ 65 // p long ru_majflt; /* page faults (hard page faults) */ 66 // * long ru_nswap; /* swaps */ 67 // p long ru_inblock; /* block input operations */ 68 // p long ru_oublock; /* block output operations */ 69 // * long ru_msgsnd; /* IPC messages sent */ 70 // * long ru_msgrcv; /* IPC messages received */ 71 // * long ru_nsignals; /* signals received */ 72 // y long ru_nvcsw; /* voluntary context switches */ 73 // y long ru_nivcsw; /* involuntary context switches */ 74 func Getrusage(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 75 which := args[0].Int() 76 addr := args[1].Pointer() 77 78 if which != linux.RUSAGE_SELF && which != linux.RUSAGE_CHILDREN && which != linux.RUSAGE_THREAD { 79 return 0, nil, linuxerr.EINVAL 80 } 81 82 ru := getrusage(t, which) 83 _, err := ru.CopyOut(t, addr) 84 return 0, nil, err 85 } 86 87 // Times implements linux syscall times(2). 88 func Times(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 89 addr := args[0].Pointer() 90 91 // Calculate the ticks first, and figure out if any additional work is 92 // necessary. Linux allows for a NULL addr, in which case only the 93 // return value is meaningful. We don't need to do anything else. 94 ticks := uintptr(ktime.NowFromContext(t).Nanoseconds() / linux.ClockTick.Nanoseconds()) 95 if addr == 0 { 96 return ticks, nil, nil 97 } 98 99 cs1 := t.ThreadGroup().CPUStats() 100 cs2 := t.ThreadGroup().JoinedChildCPUStats() 101 r := linux.Tms{ 102 UTime: linux.ClockTFromDuration(cs1.UserTime), 103 STime: linux.ClockTFromDuration(cs1.SysTime), 104 CUTime: linux.ClockTFromDuration(cs2.UserTime), 105 CSTime: linux.ClockTFromDuration(cs2.SysTime), 106 } 107 if _, err := r.CopyOut(t, addr); err != nil { 108 return 0, nil, err 109 } 110 111 return ticks, nil, nil 112 }