authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-11-02 14:52:54-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-11-02 14:52:54-04:00
log08dc840247536cffb970b9fa3974017db44ed373
tree6213eb9d720488d02ef55f7e6a0e64b235f4de70
parent5ebdc8c46c594580a95acbc7252e77ccac8d0680
parenta78e61acf9370df66c257036d7a626321691aa5d
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10088 from ziglang/std-os-perf

std: add Linux perf syscall bits

4 files changed, 372 insertions(+), 10 deletions(-)

lib/std/c/darwin.zig+3-2
......@@ -1703,8 +1703,6 @@ pub const CLOCK = struct {
17031703/// Max open files per process
17041704/// https://opensource.apple.com/source/xnu/xnu-4903.221.2/bsd/sys/syslimits.h.auto.html
17051705pub const OPEN_MAX = 10240;
1706pub const RUSAGE_SELF = 0;
1707pub const RUSAGE_CHILDREN = -1;
17081706
17091707pub const rusage = extern struct {
17101708 utime: timeval,
......@@ -1723,6 +1721,9 @@ pub const rusage = extern struct {
17231721 nsignals: isize,
17241722 nvcsw: isize,
17251723 nivcsw: isize,
1724
1725 pub const SELF = 0;
1726 pub const CHILDREN = -1;
17261727};
17271728
17281729pub const rlimit_resource = enum(c_int) {
lib/std/c/solaris.zig+4-4
......@@ -1550,10 +1550,6 @@ pub const rlimit = extern struct {
15501550 max: rlim_t,
15511551};
15521552
1553pub const RUSAGE_SELF = 0;
1554pub const RUSAGE_CHILDREN = -1;
1555pub const RUSAGE_THREAD = 1;
1556
15571553pub const rusage = extern struct {
15581554 utime: timeval,
15591555 stime: timeval,
......@@ -1571,6 +1567,10 @@ pub const rusage = extern struct {
15711567 nsignals: isize,
15721568 nvcsw: isize,
15731569 nivcsw: isize,
1570
1571 pub const SELF = 0;
1572 pub const CHILDREN = -1;
1573 pub const THREAD = 1;
15741574};
15751575
15761576pub const SHUT = struct {
lib/std/os.zig+84
......@@ -6349,3 +6349,87 @@ pub fn madvise(ptr: [*]align(mem.page_size) u8, length: usize, advice: u32) Madv
63496349 else => |err| return unexpectedErrno(err),
63506350 }
63516351}
6352
6353pub const PerfEventOpenError = error{
6354 /// Returned if the perf_event_attr size value is too small (smaller
6355 /// than PERF_ATTR_SIZE_VER0), too big (larger than the page size),
6356 /// or larger than the kernel supports and the extra bytes are not
6357 /// zero. When E2BIG is returned, the perf_event_attr size field is
6358 /// overwritten by the kernel to be the size of the structure it was
6359 /// expecting.
6360 TooBig,
6361 /// Returned when the requested event requires CAP_SYS_ADMIN permis‐
6362 /// sions (or a more permissive perf_event paranoid setting). Some
6363 /// common cases where an unprivileged process may encounter this
6364 /// error: attaching to a process owned by a different user; moni‐
6365 /// toring all processes on a given CPU (i.e., specifying the pid
6366 /// argument as -1); and not setting exclude_kernel when the para‐
6367 /// noid setting requires it.
6368 /// Also:
6369 /// Returned on many (but not all) architectures when an unsupported
6370 /// exclude_hv, exclude_idle, exclude_user, or exclude_kernel set‐
6371 /// ting is specified.
6372 /// It can also happen, as with EACCES, when the requested event re‐
6373 /// quires CAP_SYS_ADMIN permissions (or a more permissive
6374 /// perf_event paranoid setting). This includes setting a break‐
6375 /// point on a kernel address, and (since Linux 3.13) setting a ker‐
6376 /// nel function-trace tracepoint.
6377 PermissionDenied,
6378 /// Returned if another event already has exclusive access to the
6379 /// PMU.
6380 DeviceBusy,
6381 /// Each opened event uses one file descriptor. If a large number
6382 /// of events are opened, the per-process limit on the number of
6383 /// open file descriptors will be reached, and no more events can be
6384 /// created.
6385 ProcessResources,
6386 EventRequiresUnsupportedCpuFeature,
6387 /// Returned if you try to add more breakpoint
6388 /// events than supported by the hardware.
6389 TooManyBreakpoints,
6390 /// Returned if PERF_SAMPLE_STACK_USER is set in sample_type and it
6391 /// is not supported by hardware.
6392 SampleStackNotSupported,
6393 /// Returned if an event requiring a specific hardware feature is
6394 /// requested but there is no hardware support. This includes re‐
6395 /// questing low-skid events if not supported, branch tracing if it
6396 /// is not available, sampling if no PMU interrupt is available, and
6397 /// branch stacks for software events.
6398 EventNotSupported,
6399 /// Returned if PERF_SAMPLE_CALLCHAIN is requested and sam‐
6400 /// ple_max_stack is larger than the maximum specified in
6401 /// /proc/sys/kernel/perf_event_max_stack.
6402 SampleMaxStackOverflow,
6403 /// Returned if attempting to attach to a process that does not exist.
6404 ProcessNotFound,
6405} || UnexpectedError;
6406
6407pub fn perf_event_open(
6408 attr: *linux.perf_event_attr,
6409 pid: pid_t,
6410 cpu: i32,
6411 group_fd: fd_t,
6412 flags: usize,
6413) PerfEventOpenError!fd_t {
6414 const rc = system.perf_event_open(attr, pid, cpu, group_fd, flags);
6415 switch (errno(rc)) {
6416 .SUCCESS => return @intCast(fd_t, rc),
6417 .@"2BIG" => return error.TooBig,
6418 .ACCES => return error.PermissionDenied,
6419 .BADF => unreachable, // group_fd file descriptor is not valid.
6420 .BUSY => return error.DeviceBusy,
6421 .FAULT => unreachable, // Segmentation fault.
6422 .INVAL => unreachable, // Bad attr settings.
6423 .INTR => unreachable, // Mixed perf and ftrace handling for a uprobe.
6424 .MFILE => return error.ProcessResources,
6425 .NODEV => return error.EventRequiresUnsupportedCpuFeature,
6426 .NOENT => unreachable, // Invalid type setting.
6427 .NOSPC => return error.TooManyBreakpoints,
6428 .NOSYS => return error.SampleStackNotSupported,
6429 .OPNOTSUPP => return error.EventNotSupported,
6430 .OVERFLOW => return error.SampleMaxStackOverflow,
6431 .PERM => return error.PermissionDenied,
6432 .SRCH => return error.ProcessNotFound,
6433 else => |err| return unexpectedErrno(err),
6434 }
6435}
lib/std/os/linux.zig+281-4
......@@ -1638,6 +1638,23 @@ pub fn fadvise(fd: fd_t, offset: i64, len: i64, advice: usize) usize {
16381638 }
16391639}
16401640
1641pub fn perf_event_open(
1642 attr: *perf_event_attr,
1643 pid: pid_t,
1644 cpu: i32,
1645 group_fd: fd_t,
1646 flags: usize,
1647) usize {
1648 return syscall5(
1649 .perf_event_open,
1650 @ptrToInt(attr),
1651 @bitCast(usize, @as(isize, pid)),
1652 @bitCast(usize, @as(isize, cpu)),
1653 @bitCast(usize, @as(isize, group_fd)),
1654 flags,
1655 );
1656}
1657
16411658pub const E = switch (native_arch) {
16421659 .mips, .mipsel => @import("linux/errno/mips.zig").E,
16431660 .sparc, .sparcel, .sparcv9 => @import("linux/errno/sparc.zig").E,
......@@ -3781,10 +3798,6 @@ pub const MFD_HUGE_1GB = HUGETLB_FLAG_ENCODE_1GB;
37813798pub const MFD_HUGE_2GB = HUGETLB_FLAG_ENCODE_2GB;
37823799pub const MFD_HUGE_16GB = HUGETLB_FLAG_ENCODE_16GB;
37833800
3784pub const RUSAGE_SELF = 0;
3785pub const RUSAGE_CHILDREN = -1;
3786pub const RUSAGE_THREAD = 1;
3787
37883801pub const rusage = extern struct {
37893802 utime: timeval,
37903803 stime: timeval,
......@@ -3803,6 +3816,10 @@ pub const rusage = extern struct {
38033816 nvcsw: isize,
38043817 nivcsw: isize,
38053818 __reserved: [16]isize = [1]isize{0} ** 16,
3819
3820 pub const SELF = 0;
3821 pub const CHILDREN = -1;
3822 pub const THREAD = 1;
38063823};
38073824
38083825pub const cc_t = u8;
......@@ -4925,3 +4942,263 @@ pub const rtnl_link_stats64 = extern struct {
49254942 /// dropped, no handler found
49264943 rx_nohandler: u64,
49274944};
4945
4946pub const perf_event_attr = extern struct {
4947 /// Major type: hardware/software/tracepoint/etc.
4948 type: PERF.TYPE = undefined,
4949 /// Size of the attr structure, for fwd/bwd compat.
4950 size: u32 = @sizeOf(perf_event_attr),
4951 /// Type specific configuration information.
4952 config: u64 = 0,
4953
4954 sample_period_or_freq: u64 = 0,
4955 sample_type: u64 = 0,
4956 read_format: u64 = 0,
4957
4958 flags: packed struct {
4959 /// off by default
4960 disabled: bool = false,
4961 /// children inherit it
4962 inherit: bool = false,
4963 /// must always be on PMU
4964 pinned: bool = false,
4965 /// only group on PMU
4966 exclusive: bool = false,
4967 /// don't count user
4968 exclude_user: bool = false,
4969 /// ditto kernel
4970 exclude_kernel: bool = false,
4971 /// ditto hypervisor
4972 exclude_hv: bool = false,
4973 /// don't count when idle
4974 exclude_idle: bool = false,
4975 /// include mmap data
4976 mmap: bool = false,
4977 /// include comm data
4978 comm: bool = false,
4979 /// use freq, not period
4980 freq: bool = false,
4981 /// per task counts
4982 inherit_stat: bool = false,
4983 /// next exec enables
4984 enable_on_exec: bool = false,
4985 /// trace fork/exit
4986 task: bool = false,
4987 /// wakeup_watermark
4988 watermark: bool = false,
4989 /// precise_ip:
4990 ///
4991 /// 0 - SAMPLE_IP can have arbitrary skid
4992 /// 1 - SAMPLE_IP must have constant skid
4993 /// 2 - SAMPLE_IP requested to have 0 skid
4994 /// 3 - SAMPLE_IP must have 0 skid
4995 ///
4996 /// See also PERF_RECORD_MISC_EXACT_IP
4997 /// skid constraint
4998 precise_ip: u2 = 0,
4999 /// non-exec mmap data
5000 mmap_data: bool = false,
5001 /// sample_type all events
5002 sample_id_all: bool = false,
5003
5004 /// don't count in host
5005 exclude_host: bool = false,
5006 /// don't count in guest
5007 exclude_guest: bool = false,
5008
5009 /// exclude kernel callchains
5010 exclude_callchain_kernel: bool = false,
5011 /// exclude user callchains
5012 exclude_callchain_user: bool = false,
5013 /// include mmap with inode data
5014 mmap2: bool = false,
5015 /// flag comm events that are due to an exec
5016 comm_exec: bool = false,
5017 /// use @clockid for time fields
5018 use_clockid: bool = false,
5019 /// context switch data
5020 context_switch: bool = false,
5021 /// Write ring buffer from end to beginning
5022 write_backward: bool = false,
5023 /// include namespaces data
5024 namespaces: bool = false,
5025
5026 __reserved_1: u35 = 0,
5027 } = .{},
5028 /// wakeup every n events, or
5029 /// bytes before wakeup
5030 wakeup_events_or_watermark: u32 = 0,
5031
5032 bp_type: u32 = 0,
5033
5034 /// This field is also used for:
5035 /// bp_addr
5036 /// kprobe_func for perf_kprobe
5037 /// uprobe_path for perf_uprobe
5038 config1: u64 = 0,
5039 /// This field is also used for:
5040 /// bp_len
5041 /// kprobe_addr when kprobe_func == null
5042 /// probe_offset for perf_[k,u]probe
5043 config2: u64 = 0,
5044
5045 /// enum perf_branch_sample_type
5046 branch_sample_type: u64 = 0,
5047
5048 /// Defines set of user regs to dump on samples.
5049 /// See asm/perf_regs.h for details.
5050 sample_regs_user: u64 = 0,
5051
5052 /// Defines size of the user stack to dump on samples.
5053 sample_stack_user: u32 = 0,
5054
5055 clockid: i32 = 0,
5056 /// Defines set of regs to dump for each sample
5057 /// state captured on:
5058 /// - precise = 0: PMU interrupt
5059 /// - precise > 0: sampled instruction
5060 ///
5061 /// See asm/perf_regs.h for details.
5062 sample_regs_intr: u64 = 0,
5063
5064 /// Wakeup watermark for AUX area
5065 aux_watermark: u32 = 0,
5066 sample_max_stack: u16 = 0,
5067 /// Align to u64
5068 __reserved_2: u16 = 0,
5069};
5070
5071pub const PERF = struct {
5072 pub const TYPE = enum(u32) {
5073 HARDWARE,
5074 SOFTWARE,
5075 TRACEPOINT,
5076 HW_CACHE,
5077 RAW,
5078 BREAKPOINT,
5079 MAX,
5080 };
5081
5082 pub const COUNT = struct {
5083 pub const HW = enum(u32) {
5084 CPU_CYCLES,
5085 INSTRUCTIONS,
5086 CACHE_REFERENCES,
5087 CACHE_MISSES,
5088 BRANCH_INSTRUCTIONS,
5089 BRANCH_MISSES,
5090 BUS_CYCLES,
5091 STALLED_CYCLES_FRONTEND,
5092 STALLED_CYCLES_BACKEND,
5093 REF_CPU_CYCLES,
5094 MAX,
5095
5096 pub const CACHE = enum(u32) {
5097 L1D,
5098 L1I,
5099 LL,
5100 DTLB,
5101 ITLB,
5102 BPU,
5103 NODE,
5104 MAX,
5105
5106 pub const OP = enum(u32) {
5107 READ,
5108 WRITE,
5109 PREFETCH,
5110 MAX,
5111 };
5112
5113 pub const RESULT = enum(u32) {
5114 ACCESS,
5115 MISS,
5116 MAX,
5117 };
5118 };
5119 };
5120
5121 pub const SW = enum(u32) {
5122 CPU_CLOCK,
5123 TASK_CLOCK,
5124 PAGE_FAULTS,
5125 CONTEXT_SWITCHES,
5126 CPU_MIGRATIONS,
5127 PAGE_FAULTS_MIN,
5128 PAGE_FAULTS_MAJ,
5129 ALIGNMENT_FAULTS,
5130 EMULATION_FAULTS,
5131 DUMMY,
5132 BPF_OUTPUT,
5133 MAX,
5134 };
5135 };
5136
5137 pub const SAMPLE = struct {
5138 pub const IP = 1;
5139 pub const TID = 2;
5140 pub const TIME = 4;
5141 pub const ADDR = 8;
5142 pub const READ = 16;
5143 pub const CALLCHAIN = 32;
5144 pub const ID = 64;
5145 pub const CPU = 128;
5146 pub const PERIOD = 256;
5147 pub const STREAM_ID = 512;
5148 pub const RAW = 1024;
5149 pub const BRANCH_STACK = 2048;
5150 pub const REGS_USER = 4096;
5151 pub const STACK_USER = 8192;
5152 pub const WEIGHT = 16384;
5153 pub const DATA_SRC = 32768;
5154 pub const IDENTIFIER = 65536;
5155 pub const TRANSACTION = 131072;
5156 pub const REGS_INTR = 262144;
5157 pub const PHYS_ADDR = 524288;
5158 pub const MAX = 1048576;
5159
5160 pub const BRANCH = struct {
5161 pub const USER = 1 << 0;
5162 pub const KERNEL = 1 << 1;
5163 pub const HV = 1 << 2;
5164 pub const ANY = 1 << 3;
5165 pub const ANY_CALL = 1 << 4;
5166 pub const ANY_RETURN = 1 << 5;
5167 pub const IND_CALL = 1 << 6;
5168 pub const ABORT_TX = 1 << 7;
5169 pub const IN_TX = 1 << 8;
5170 pub const NO_TX = 1 << 9;
5171 pub const COND = 1 << 10;
5172 pub const CALL_STACK = 1 << 11;
5173 pub const IND_JUMP = 1 << 12;
5174 pub const CALL = 1 << 13;
5175 pub const NO_FLAGS = 1 << 14;
5176 pub const NO_CYCLES = 1 << 15;
5177 pub const TYPE_SAVE = 1 << 16;
5178 pub const MAX = 1 << 17;
5179 };
5180 };
5181
5182 pub const FLAG = struct {
5183 pub const FD_NO_GROUP = 1 << 0;
5184 pub const FD_OUTPUT = 1 << 1;
5185 pub const PID_CGROUP = 1 << 2;
5186 pub const FD_CLOEXEC = 1 << 3;
5187 };
5188
5189 pub const EVENT_IOC = struct {
5190 pub const ENABLE = 9216;
5191 pub const DISABLE = 9217;
5192 pub const REFRESH = 9218;
5193 pub const RESET = 9219;
5194 pub const PERIOD = 1074275332;
5195 pub const SET_OUTPUT = 9221;
5196 pub const SET_FILTER = 1074275334;
5197 pub const SET_BPF = 1074013192;
5198 pub const PAUSE_OUTPUT = 1074013193;
5199 pub const QUERY_BPF = 3221758986;
5200 pub const MODIFY_ATTRIBUTES = 1074275339;
5201 };
5202
5203 pub const IOC_FLAG_GROUP = 1;
5204};