1#!/usr/sbin/dtrace -s
2
3/*-
4 * Copyright (c) 2012-2016 Ryan Stone
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29/*
30 * DTrace script for collecting schedgraph data.  Run the output
31 * of this script through make_ktr before feeding it into
32 * schedgraph.py
33 *
34 * e.g.
35 * # ./schedgraph.d > /tmp/sched.out
36 * # ./make_ktr.sh /tmp/sched.out /tmp/sched.ktr
37 * # python schedgraph.py /tmp/sched.ktr 1
38 */
39
40#pragma D option quiet
41#pragma D option bufpolicy=ring
42
43inline int TDF_IDLETD = 0x00000020;
44
45/*
46 * Reasons that the current thread can not be run yet.
47 * More than one may apply.
48 */
49inline int TDI_SUSPENDED = 0x0001;	/* On suspension queue. */
50inline int TDI_SLEEPING = 0x0002;	/* Actually asleep! (tricky). */
51inline int TDI_SWAPPED = 0x0004;	/* Stack not in mem.  Bad juju if run. */
52inline int TDI_LOCK = 0x0008;		/* Stopped on a lock. */
53inline int TDI_IWAIT = 0x0010;		/* Awaiting interrupt. */
54
55inline string KTDSTATE[struct thread * td] = \
56	(((td)->td_inhibitors & TDI_SLEEPING) != 0 ? "sleep"  :		\
57	((td)->td_inhibitors & TDI_SUSPENDED) != 0 ? "suspended" :	\
58	((td)->td_inhibitors & TDI_SWAPPED) != 0 ? "swapped" :		\
59	((td)->td_inhibitors & TDI_LOCK) != 0 ? "blocked" :		\
60	((td)->td_inhibitors & TDI_IWAIT) != 0 ? "iwait" : "yielding");
61
62/*
63 * NOCPU changed from 255 to -1 at some point.  This hacky test will work on a
64 * kernel compiled with either version.
65 */
66inline int is_nocpu[int cpu] = cpu < 0 || cpu > `mp_maxid;
67
68sched:::load-change
69/ is_nocpu[args[0]] /
70{
71	printf("%d %d KTRGRAPH group:\"load\", id:\"global load\", counter:\"%d\", attributes: \"none\"\n", cpu, timestamp, args[1]);
72}
73
74sched:::load-change
75/ !is_nocpu[args[0]] /
76{
77	printf("%d %d KTRGRAPH group:\"load\", id:\"CPU %d load\", counter:\"%d\", attributes: \"none\"\n", cpu, timestamp, args[0], args[1]);
78
79}
80
81proc:::exit
82{
83	printf("%d %d KTRGRAPH group:\"thread\", id:\"%s/%s tid %d\", state:\"proc exit\", attributes: prio:td\n", cpu, timestamp, curthread->td_proc->p_comm, curthread->td_name, curthread->td_tid);
84}
85
86proc:::lwp-exit
87{
88	printf("%d %d KTRGRAPH group:\"thread\", id:\"%s/%s tid %d\", state:\"exit\", attributes: prio:td\n", cpu, timestamp, curthread->td_proc->p_comm, curthread->td_name, curthread->td_tid);
89}
90
91sched:::change-pri
92{
93	printf("%d %d KTRGRAPH group:\"thread\", id:\"%s/%s tid %d\", point:\"priority change\", attributes: prio:%d, new prio:%d, linkedto:\"%s/%s tid %d\"\n", cpu, timestamp, args[0]->td_proc->p_comm, args[0]->td_name, args[0]->td_tid, args[0]->td_priority, arg2, curthread->td_proc->p_comm, curthread->td_name, curthread->td_tid);
94}
95
96sched:::lend-pri
97{
98	printf("%d %d KTRGRAPH group:\"thread\", id:\"%s/%s tid %d\", point:\"lend prio\", attributes: prio:%d, new prio:%d, linkedto:\"%s/%s tid %d\"\n", cpu, timestamp, curthread->td_proc->p_comm, curthread->td_name, curthread->td_tid, args[0]->td_priority, arg2, args[0]->td_proc->p_comm, args[0]->td_name, args[0]->td_tid);
99}
100
101sched:::enqueue
102{
103	printf("%d %d KTRGRAPH group:\"thread\", id:\"%s/%s tid %d\", state:\"runq add\", attributes: prio:%d, linkedto:\"%s/%s tid %d\"\n", cpu, timestamp, args[0]->td_proc->p_comm, args[0]->td_name, args[0]->td_tid, args[0]->td_priority, curthread->td_proc->p_comm, curthread->td_name, curthread->td_tid);
104	printf("%d %d KTRGRAPH group:\"thread\", id:\"%s/%s tid %d\", point:\"wokeup\", attributes: linkedto:\"%s/%s tid %d\"\n", cpu, timestamp, curthread->td_proc->p_comm, curthread->td_name, curthread->td_tid, args[0]->td_proc->p_comm, args[0]->td_name, args[0]->td_tid);
105}
106
107sched:::dequeue
108{
109	printf("%d %d KTRGRAPH group:\"thread\", id:\"%s/%s tid %d\", state:\"runq rem\", attributes: prio:%d, linkedto:\"%s/%s tid %d\"\n", cpu, timestamp, args[0]->td_proc->p_comm, args[0]->td_name, args[0]->td_tid, args[0]->td_priority, curthread->td_proc->p_comm, curthread->td_name, curthread->td_tid);
110}
111
112sched:::tick
113{
114	printf("%d %d KTRGRAPH group:\"thread\", id:\"%s/%s tid %d\", point:\"statclock\", attributes: prio:%d, stathz:%d\n", cpu, timestamp, args[0]->td_proc->p_comm, args[0]->td_name, args[0]->td_tid, args[0]->td_priority, `stathz ? `stathz : `hz);
115}
116
117sched:::off-cpu
118/ curthread->td_flags & TDF_IDLETD /
119{
120	printf("%d %d KTRGRAPH group:\"thread\", id:\"%s/%s tid %d\", state:\"idle\", attributes: prio:%d\n", cpu, timestamp, curthread->td_proc->p_comm, curthread->td_name, curthread->td_tid, curthread->td_priority);
121}
122
123sched:::off-cpu
124/ (curthread->td_flags & TDF_IDLETD) == 0 /
125{
126	printf("%d %d KTRGRAPH group:\"thread\", id:\"%s/%s tid %d\", state:\"%s\", attributes: prio:%d, wmesg:\"%s\", lockname:\"%s\"\n", cpu, timestamp, curthread->td_proc->p_comm, curthread->td_name, curthread->td_tid, KTDSTATE[curthread], curthread->td_priority, curthread->td_wmesg ? stringof(curthread->td_wmesg) : "(null)", curthread->td_lockname ? stringof(curthread->td_lockname) : "(null)");
127}
128
129sched:::on-cpu
130{
131	printf("%d %d KTRGRAPH group:\"thread\", id:\"%s/%s tid %d\", state:\"running\", attributes: prio:%d\n", cpu, timestamp, curthread->td_proc->p_comm, curthread->td_name, curthread->td_tid, curthread->td_priority);
132}
133
134