gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/grpc/internal/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   */
    18  
    19  // Package syscall provides functionalities that grpc uses to get low-level operating system
    20  // stats/info.
    21  package syscall
    22  
    23  import (
    24  	"fmt"
    25  	"net"
    26  	"syscall"
    27  	"time"
    28  
    29  	"gitee.com/ks-custle/core-gm/grpc/grpclog"
    30  	"golang.org/x/sys/unix"
    31  )
    32  
    33  var logger = grpclog.Component("core")
    34  
    35  // GetCPUTime returns the how much CPU time has passed since the start of this process.
    36  func GetCPUTime() int64 {
    37  	var ts unix.Timespec
    38  	if err := unix.ClockGettime(unix.CLOCK_PROCESS_CPUTIME_ID, &ts); err != nil {
    39  		logger.Fatal(err)
    40  	}
    41  	return ts.Nano()
    42  }
    43  
    44  // Rusage is an alias for syscall.Rusage under linux environment.
    45  type Rusage = syscall.Rusage
    46  
    47  // GetRusage returns the resource usage of current process.
    48  func GetRusage() *Rusage {
    49  	rusage := new(Rusage)
    50  	syscall.Getrusage(syscall.RUSAGE_SELF, rusage)
    51  	return rusage
    52  }
    53  
    54  // CPUTimeDiff returns the differences of user CPU time and system CPU time used
    55  // between two Rusage structs.
    56  func CPUTimeDiff(first *Rusage, latest *Rusage) (float64, float64) {
    57  	var (
    58  		utimeDiffs  = latest.Utime.Sec - first.Utime.Sec
    59  		utimeDiffus = latest.Utime.Usec - first.Utime.Usec
    60  		stimeDiffs  = latest.Stime.Sec - first.Stime.Sec
    61  		stimeDiffus = latest.Stime.Usec - first.Stime.Usec
    62  	)
    63  
    64  	uTimeElapsed := float64(utimeDiffs) + float64(utimeDiffus)*1.0e-6
    65  	sTimeElapsed := float64(stimeDiffs) + float64(stimeDiffus)*1.0e-6
    66  
    67  	return uTimeElapsed, sTimeElapsed
    68  }
    69  
    70  // SetTCPUserTimeout sets the TCP user timeout on a connection's socket
    71  func SetTCPUserTimeout(conn net.Conn, timeout time.Duration) error {
    72  	tcpconn, ok := conn.(*net.TCPConn)
    73  	if !ok {
    74  		// not a TCP connection. exit early
    75  		return nil
    76  	}
    77  	rawConn, err := tcpconn.SyscallConn()
    78  	if err != nil {
    79  		return fmt.Errorf("error getting raw connection: %v", err)
    80  	}
    81  	err = rawConn.Control(func(fd uintptr) {
    82  		err = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT, int(timeout/time.Millisecond))
    83  	})
    84  	if err != nil {
    85  		return fmt.Errorf("error setting option on socket: %v", err)
    86  	}
    87  
    88  	return nil
    89  }
    90  
    91  // GetTCPUserTimeout gets the TCP user timeout on a connection's socket
    92  func GetTCPUserTimeout(conn net.Conn) (opt int, err error) {
    93  	tcpconn, ok := conn.(*net.TCPConn)
    94  	if !ok {
    95  		err = fmt.Errorf("conn is not *net.TCPConn. got %T", conn)
    96  		return
    97  	}
    98  	rawConn, err := tcpconn.SyscallConn()
    99  	if err != nil {
   100  		err = fmt.Errorf("error getting raw connection: %v", err)
   101  		return
   102  	}
   103  	err = rawConn.Control(func(fd uintptr) {
   104  		opt, err = syscall.GetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT)
   105  	})
   106  	if err != nil {
   107  		err = fmt.Errorf("error getting option on socket: %v", err)
   108  		return
   109  	}
   110  
   111  	return
   112  }