1# futex contention
2# (c) 2010, Arnaldo Carvalho de Melo <acme@redhat.com>
3# Licensed under the terms of the GNU GPL License version 2
4#
5# Translation of:
6#
7# http://sourceware.org/systemtap/wiki/WSFutexContention
8#
9# to perf python scripting.
10#
11# Measures futex contention
12
13from __future__ import print_function
14
15import os
16import sys
17sys.path.append(os.environ['PERF_EXEC_PATH'] +
18                '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
19from Util import *
20
21process_names = {}
22thread_thislock = {}
23thread_blocktime = {}
24
25lock_waits = {}  # long-lived stats on (tid,lock) blockage elapsed time
26process_names = {}  # long-lived pid-to-execname mapping
27
28
29def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
30                              nr, uaddr, op, val, utime, uaddr2, val3):
31    cmd = op & FUTEX_CMD_MASK
32    if cmd != FUTEX_WAIT:
33        return  # we don't care about originators of WAKE events
34
35    process_names[tid] = comm
36    thread_thislock[tid] = uaddr
37    thread_blocktime[tid] = nsecs(s, ns)
38
39
40def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
41                             nr, ret):
42    if tid in thread_blocktime:
43        elapsed = nsecs(s, ns) - thread_blocktime[tid]
44        add_stats(lock_waits, (tid, thread_thislock[tid]), elapsed)
45        del thread_blocktime[tid]
46        del thread_thislock[tid]
47
48
49def trace_begin():
50    print("Press control+C to stop and show the summary")
51
52
53def trace_end():
54    for (tid, lock) in lock_waits:
55        min, max, avg, count = lock_waits[tid, lock]
56        print("%s[%d] lock %x contended %d times, %d avg ns [max: %d ns, min %d ns]" %
57              (process_names[tid], tid, lock, count, avg, max, min))
58