18c2ecf20Sopenharmony_ci#! /usr/bin/env python
28c2ecf20Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0-only
38c2ecf20Sopenharmony_ci# -*- python -*-
48c2ecf20Sopenharmony_ci# -*- coding: utf-8 -*-
58c2ecf20Sopenharmony_ci#   twatch - Experimental use of the perf python interface
68c2ecf20Sopenharmony_ci#   Copyright (C) 2011 Arnaldo Carvalho de Melo <acme@redhat.com>
78c2ecf20Sopenharmony_ci#
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ciimport perf
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_cidef main(context_switch = 0, thread = -1):
128c2ecf20Sopenharmony_ci	cpus = perf.cpu_map()
138c2ecf20Sopenharmony_ci	threads = perf.thread_map(thread)
148c2ecf20Sopenharmony_ci	evsel = perf.evsel(type	  = perf.TYPE_SOFTWARE,
158c2ecf20Sopenharmony_ci			   config = perf.COUNT_SW_DUMMY,
168c2ecf20Sopenharmony_ci			   task = 1, comm = 1, mmap = 0, freq = 0,
178c2ecf20Sopenharmony_ci			   wakeup_events = 1, watermark = 1,
188c2ecf20Sopenharmony_ci			   sample_id_all = 1, context_switch = context_switch,
198c2ecf20Sopenharmony_ci			   sample_type = perf.SAMPLE_PERIOD | perf.SAMPLE_TID | perf.SAMPLE_CPU)
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci	"""What we want are just the PERF_RECORD_ lifetime events for threads,
228c2ecf20Sopenharmony_ci	 using the default, PERF_TYPE_HARDWARE + PERF_COUNT_HW_CYCLES & freq=1
238c2ecf20Sopenharmony_ci	 (the default), makes perf reenable irq_vectors:local_timer_entry, when
248c2ecf20Sopenharmony_ci	 disabling nohz, not good for some use cases where all we want is to get
258c2ecf20Sopenharmony_ci	 threads comes and goes... So use (perf.TYPE_SOFTWARE, perf_COUNT_SW_DUMMY,
268c2ecf20Sopenharmony_ci	 freq=0) instead."""
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	evsel.open(cpus = cpus, threads = threads);
298c2ecf20Sopenharmony_ci	evlist = perf.evlist(cpus, threads)
308c2ecf20Sopenharmony_ci	evlist.add(evsel)
318c2ecf20Sopenharmony_ci	evlist.mmap()
328c2ecf20Sopenharmony_ci	while True:
338c2ecf20Sopenharmony_ci		evlist.poll(timeout = -1)
348c2ecf20Sopenharmony_ci		for cpu in cpus:
358c2ecf20Sopenharmony_ci			event = evlist.read_on_cpu(cpu)
368c2ecf20Sopenharmony_ci			if not event:
378c2ecf20Sopenharmony_ci				continue
388c2ecf20Sopenharmony_ci			print("cpu: {0}, pid: {1}, tid: {2} {3}".format(event.sample_cpu,
398c2ecf20Sopenharmony_ci                                                                        event.sample_pid,
408c2ecf20Sopenharmony_ci                                                                        event.sample_tid,
418c2ecf20Sopenharmony_ci                                                                        event))
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ciif __name__ == '__main__':
448c2ecf20Sopenharmony_ci    """
458c2ecf20Sopenharmony_ci	To test the PERF_RECORD_SWITCH record, pick a pid and replace
468c2ecf20Sopenharmony_ci	in the following line.
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	Example output:
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cicpu: 3, pid: 31463, tid: 31593 { type: context_switch, next_prev_pid: 31463, next_prev_tid: 31593, switch_out: 1 }
518c2ecf20Sopenharmony_cicpu: 1, pid: 31463, tid: 31489 { type: context_switch, next_prev_pid: 31463, next_prev_tid: 31489, switch_out: 1 }
528c2ecf20Sopenharmony_cicpu: 2, pid: 31463, tid: 31496 { type: context_switch, next_prev_pid: 31463, next_prev_tid: 31496, switch_out: 1 }
538c2ecf20Sopenharmony_cicpu: 3, pid: 31463, tid: 31491 { type: context_switch, next_prev_pid: 31463, next_prev_tid: 31491, switch_out: 0 }
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	It is possible as well to use event.misc & perf.PERF_RECORD_MISC_SWITCH_OUT
568c2ecf20Sopenharmony_ci	to figure out if this is a context switch in or out of the monitored threads.
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	If bored, please add command line option parsing support for these options :-)
598c2ecf20Sopenharmony_ci    """
608c2ecf20Sopenharmony_ci    # main(context_switch = 1, thread = 31463)
618c2ecf20Sopenharmony_ci    main()
62