-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
pkg/trace/watchdog: add user cpu reader for AIX
- Loading branch information
Showing
4 changed files
with
110 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
// Unless explicitly stated otherwise all files in this repository are licensed | ||
// under the Apache License Version 2.0. | ||
// This product includes software developed at Datadog (https://www.datadoghq.com/). | ||
// Copyright 2016-2020 Datadog, Inc. | ||
|
||
package watchdog | ||
|
||
import ( | ||
"encoding/binary" | ||
"fmt" | ||
"os" | ||
) | ||
|
||
// From proc(5) on AIX 7.2 | ||
// status | ||
// Contains state information about the process and one of its | ||
// representative thread. The file is formatted as a struct pstatus | ||
// type containing the following members: | ||
// | ||
// uint32_t pr_flag; /* process flags from proc struct p_flag */ | ||
// uint32_t pr_flag2; /* process flags from proc struct p_flag2 */ | ||
// uint32_t pr_flags; /* /proc flags */ | ||
// uint32_t pr_nlwp; /* number of threads in the process */ | ||
// char pr_stat; /* process state from proc p_stat */ | ||
// char pr_dmodel; /* data model for the process */ | ||
// char pr__pad1[6]; /* reserved for future use */ | ||
// pr_sigset_t pr_sigpend; /* set of process pending signals */ | ||
// prptr64_t pr_brkbase; /* address of the process heap */ | ||
// uint64_t pr_brksize; /* size of the process heap, in bytes */ | ||
// prptr64_t pr_stkbase; /* address of the process stack */ | ||
// uint64_t pr_stksize; /* size of the process stack, in bytes */ | ||
// pid64_t pr_pid; /* process id */ | ||
// pid64_t pr_ppid; /* parent process id */ | ||
// pid64_t pr_pgid; /* process group id */ | ||
// pid64_t pr_sid; /* session id */ | ||
// struct pr_timestruc64_t pr_utime; /* process user cpu time */ | ||
// struct pr_timestruc64_t pr_stime; /* process system cpu time */ | ||
// struct pr_timestruc64_t pr_cutime; /* sum of children's user times */ | ||
// struct pr_timestruc64_t pr_cstime; /* sum of children's system times */ | ||
// pr_sigset_t pr_sigtrace; /* mask of traced signals */ | ||
// fltset_t pr_flttrace; /* mask of traced hardware faults */ | ||
// uint32_t pr_sysentry_offset; /* offset into pstatus file of sysset_t | ||
// * identifying system calls traced on | ||
// | ||
// * entry. If 0, then no entry syscalls | ||
// * are being traced. */ | ||
// uint32_t pr_sysexit_offset; /* offset into pstatus file of sysset_t | ||
// * identifying system calls traced on | ||
// * exit. If 0, then no exit syscalls | ||
// * are being traced. */ | ||
// uint64_t pr__pad[8]; /* reserved for future use */ | ||
// lwpstatus_t pr_lwp; /* "representative" thread status */ | ||
// | ||
// From /usr/include/sys/procfs.h | ||
// typedef struct pr_sigset | ||
// { | ||
// uint64_t ss_set[4]; /* signal set */ | ||
// } pr_sigset_t; | ||
// | ||
// typedef struct pr_timestruc64 | ||
// { | ||
// int64_t tv_sec; /* 64 bit time_t value */ | ||
// int32_t tv_nsec; /* 32 bit suseconds_t value */ | ||
// uint32_t __pad; /* reserved for future use */ | ||
// } pr_timestruc64_t; | ||
// | ||
// typedef void * prptr64_t; | ||
// | ||
// The fields before the user cpu time (pr_utime) are: | ||
// uint32_t pr_flag; 4 4 | ||
// uint32_t pr_flag2; 4 8 | ||
// uint32_t pr_flags; 4 12 | ||
// uint32_t pr_nlwp; 4 16 | ||
// char pr_stat; 1 17 | ||
// char pr_dmodel; 1 18 | ||
// char pr__pad1[6]; 6 24 | ||
// pr_sigset_t pr_sigpend; (4 * 8) = 32 56 | ||
// prptr64_t pr_brkbase; 8 64 | ||
// uint64_t pr_brksize; 8 72 | ||
// prptr64_t pr_stkbase; 8 80 | ||
// uint64_t pr_stksize; 8 88 | ||
// pid64_t pr_pid; 8 96 | ||
// pid64_t pr_ppid; 8 104 | ||
// pid64_t pr_pgid; 8 112 | ||
// pid64_t pr_sid; 8 120 | ||
// total: 120 | ||
// followed by: | ||
// struct pr_timestruc64_t pr_utime; /* process user cpu time */ | ||
|
||
// As explained above, we will skip 120 bytes into the status file to locate the user CPU time. | ||
const skip = 120 | ||
|
||
func cpuTimeUser(pid int32) (float64, error) { | ||
f, err := os.Open(fmt.Sprintf("/proc/%d/status", pid)) | ||
if err != nil { | ||
return 0, err | ||
} | ||
defer f.Close() | ||
f.Seek(skip, os.SEEK_SET) | ||
var userSecs int64 | ||
var userNsecs int32 | ||
binary.Read(f, binary.BigEndian, &userSecs) | ||
binary.Read(f, binary.BigEndian, &userNsecs) | ||
time := float64(userSecs) + (float64(userNsecs) / 1000000000) | ||
return time, nil | ||
} |