gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

syscall_linux.go (3214B)


      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 	"golang.org/x/sys/unix"
     30 	"google.golang.org/grpc/grpclog"
     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 }