1#!/usr/bin/env python
2# Copyright (c) 2016 PLUMgrid
3# Licensed under the Apache License, Version 2.0 (the "License")
4
5import bcc
6import ctypes
7import multiprocessing
8import os
9import time
10import unittest
11
12class TestPerfCounter(unittest.TestCase):
13    def test_cycles(self):
14        text = """
15BPF_PERF_ARRAY(cnt1, NUM_CPUS);
16BPF_ARRAY(prev, u64, NUM_CPUS);
17BPF_HISTOGRAM(dist);
18int do_sys_getuid(void *ctx) {
19    u32 cpu = bpf_get_smp_processor_id();
20    u64 val = cnt1.perf_read(CUR_CPU_IDENTIFIER);
21
22    if (((s64)val < 0) && ((s64)val > -256))
23        return 0;
24
25    prev.update(&cpu, &val);
26    return 0;
27}
28int do_ret_sys_getuid(void *ctx) {
29    u32 cpu = bpf_get_smp_processor_id();
30    u64 val = cnt1.perf_read(CUR_CPU_IDENTIFIER);
31
32    if (((s64)val < 0) && ((s64)val > -256))
33        return 0;
34
35    u64 *prevp = prev.lookup(&cpu);
36    if (prevp)
37        dist.increment(bpf_log2l(val - *prevp));
38    return 0;
39}
40"""
41        b = bcc.BPF(text=text, debug=0,
42                cflags=["-DNUM_CPUS=%d" % multiprocessing.cpu_count()])
43        event_name = b.get_syscall_fnname("getuid")
44        b.attach_kprobe(event=event_name, fn_name="do_sys_getuid")
45        b.attach_kretprobe(event=event_name, fn_name="do_ret_sys_getuid")
46        cnt1 = b["cnt1"]
47        try:
48            cnt1.open_perf_event(bcc.PerfType.HARDWARE, bcc.PerfHWConfig.CPU_CYCLES)
49        except:
50            if ctypes.get_errno() == 2:
51                raise self.skipTest("hardware events unsupported")
52            raise
53        for i in range(0, 100):
54            os.getuid()
55        b["dist"].print_log2_hist()
56
57if __name__ == "__main__":
58    unittest.main()
59