github.com/cloudwego/kitex@v0.9.0/pkg/remote/trans/nphttp2/grpc/syscall/syscall_linux.go (about) 1 /* 2 * 3 * Copyright 2018 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 * This file may have been modified by CloudWeGo authors. All CloudWeGo 18 * Modifications are Copyright 2021 CloudWeGo Authors. 19 */ 20 21 // Package syscall provides functionalities that grpc uses to get low-level operating system 22 // stats/info. 23 package syscall 24 25 import ( 26 "fmt" 27 "net" 28 "syscall" 29 "time" 30 31 "golang.org/x/sys/unix" 32 33 "github.com/cloudwego/kitex/pkg/klog" 34 ) 35 36 // GetCPUTime returns the how much CPU time has passed since the start of this process. 37 func GetCPUTime() int64 { 38 var ts unix.Timespec 39 if err := unix.ClockGettime(unix.CLOCK_PROCESS_CPUTIME_ID, &ts); err != nil { 40 klog.Fatal(err) 41 } 42 return ts.Nano() 43 } 44 45 // Rusage is an alias for syscall.Rusage under linux environment. 46 type Rusage = syscall.Rusage 47 48 // GetRusage returns the resource usage of current process. 49 func GetRusage() *Rusage { 50 rusage := new(Rusage) 51 syscall.Getrusage(syscall.RUSAGE_SELF, rusage) 52 return rusage 53 } 54 55 // CPUTimeDiff returns the differences of user CPU time and system CPU time used 56 // between two Rusage structs. 57 func CPUTimeDiff(first, latest *Rusage) (float64, float64) { 58 var ( 59 utimeDiffs = latest.Utime.Sec - first.Utime.Sec 60 utimeDiffus = latest.Utime.Usec - first.Utime.Usec 61 stimeDiffs = latest.Stime.Sec - first.Stime.Sec 62 stimeDiffus = latest.Stime.Usec - first.Stime.Usec 63 ) 64 65 uTimeElapsed := float64(utimeDiffs) + float64(utimeDiffus)*1.0e-6 66 sTimeElapsed := float64(stimeDiffs) + float64(stimeDiffus)*1.0e-6 67 68 return uTimeElapsed, sTimeElapsed 69 } 70 71 // SetTCPUserTimeout sets the TCP user timeout on a connection's socket 72 func SetTCPUserTimeout(conn net.Conn, timeout time.Duration) error { 73 tcpconn, ok := conn.(*net.TCPConn) 74 if !ok { 75 // not a TCP connection. exit early 76 return nil 77 } 78 rawConn, err := tcpconn.SyscallConn() 79 if err != nil { 80 return fmt.Errorf("error getting raw connection: %v", err) 81 } 82 err = rawConn.Control(func(fd uintptr) { 83 err = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT, int(timeout/time.Millisecond)) 84 }) 85 if err != nil { 86 return fmt.Errorf("error setting option on socket: %v", err) 87 } 88 89 return nil 90 } 91 92 // GetTCPUserTimeout gets the TCP user timeout on a connection's socket 93 func GetTCPUserTimeout(conn net.Conn) (opt int, err error) { 94 tcpconn, ok := conn.(*net.TCPConn) 95 if !ok { 96 err = fmt.Errorf("conn is not *net.TCPConn. got %T", conn) 97 return 98 } 99 rawConn, err := tcpconn.SyscallConn() 100 if err != nil { 101 err = fmt.Errorf("error getting raw connection: %v", err) 102 return 103 } 104 err = rawConn.Control(func(fd uintptr) { 105 opt, err = syscall.GetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT) 106 }) 107 if err != nil { 108 err = fmt.Errorf("error getting option on socket: %v", err) 109 return 110 } 111 112 return 113 }