github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/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/MerlinKodo/gvisor/pkg/abi/linux" 19 "github.com/MerlinKodo/gvisor/pkg/errors/linuxerr" 20 "github.com/MerlinKodo/gvisor/pkg/sentry/arch" 21 "github.com/MerlinKodo/gvisor/pkg/sentry/kernel" 22 ktime "github.com/MerlinKodo/gvisor/pkg/sentry/kernel/time" 23 "github.com/MerlinKodo/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 // 55 // marked "y" are supported now 56 // marked "*" are not used on Linux 57 // marked "p" are pending for support 58 // 59 // y struct timeval ru_utime; /* user CPU time used */ 60 // y struct timeval ru_stime; /* system CPU time used */ 61 // p long ru_maxrss; /* maximum resident set size */ 62 // * long ru_ixrss; /* integral shared memory size */ 63 // * long ru_idrss; /* integral unshared data size */ 64 // * long ru_isrss; /* integral unshared stack size */ 65 // p long ru_minflt; /* page reclaims (soft page faults) */ 66 // p long ru_majflt; /* page faults (hard page faults) */ 67 // * long ru_nswap; /* swaps */ 68 // p long ru_inblock; /* block input operations */ 69 // p long ru_oublock; /* block output operations */ 70 // * long ru_msgsnd; /* IPC messages sent */ 71 // * long ru_msgrcv; /* IPC messages received */ 72 // * long ru_nsignals; /* signals received */ 73 // y long ru_nvcsw; /* voluntary context switches */ 74 // y long ru_nivcsw; /* involuntary context switches */ 75 func Getrusage(t *kernel.Task, sysno uintptr, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 76 which := args[0].Int() 77 addr := args[1].Pointer() 78 79 if which != linux.RUSAGE_SELF && which != linux.RUSAGE_CHILDREN && which != linux.RUSAGE_THREAD { 80 return 0, nil, linuxerr.EINVAL 81 } 82 83 ru := getrusage(t, which) 84 _, err := ru.CopyOut(t, addr) 85 return 0, nil, err 86 } 87 88 // Times implements linux syscall times(2). 89 func Times(t *kernel.Task, sysno uintptr, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 90 addr := args[0].Pointer() 91 92 // Calculate the ticks first, and figure out if any additional work is 93 // necessary. Linux allows for a NULL addr, in which case only the 94 // return value is meaningful. We don't need to do anything else. 95 ticks := uintptr(ktime.NowFromContext(t).Nanoseconds() / linux.ClockTick.Nanoseconds()) 96 if addr == 0 { 97 return ticks, nil, nil 98 } 99 100 cs1 := t.ThreadGroup().CPUStats() 101 cs2 := t.ThreadGroup().JoinedChildCPUStats() 102 r := linux.Tms{ 103 UTime: linux.ClockTFromDuration(cs1.UserTime), 104 STime: linux.ClockTFromDuration(cs1.SysTime), 105 CUTime: linux.ClockTFromDuration(cs2.UserTime), 106 CSTime: linux.ClockTFromDuration(cs2.SysTime), 107 } 108 if _, err := r.CopyOut(t, addr); err != nil { 109 return 0, nil, err 110 } 111 112 return ticks, nil, nil 113 }