xref: /freebsd/tools/sched/schedgraph.d (revision 0a36787e4c1fa0cf77dcf83be0867178476e372b)
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  * $FreeBSD$
29  */
30 
31 /*
32  * DTrace script for collecting schedgraph data.  Run the output
33  * of this script through make_ktr before feeding it into
34  * schedgraph.py
35  *
36  * e.g.
37  * # ./schedgraph.d > /tmp/sched.out
38  * # ./make_ktr.sh /tmp/sched.out /tmp/sched.ktr
39  * # python schedgraph.py /tmp/sched.ktr 1
40  */
41 
42 #pragma D option quiet
43 #pragma D option bufpolicy=ring
44 
45 inline int TDF_IDLETD = 0x00000020;
46 
47 /*
48  * Reasons that the current thread can not be run yet.
49  * More than one may apply.
50  */
51 inline int TDI_SUSPENDED = 0x0001;	/* On suspension queue. */
52 inline int TDI_SLEEPING = 0x0002;	/* Actually asleep! (tricky). */
53 inline int TDI_SWAPPED = 0x0004;	/* Stack not in mem.  Bad juju if run. */
54 inline int TDI_LOCK = 0x0008;		/* Stopped on a lock. */
55 inline int TDI_IWAIT = 0x0010;		/* Awaiting interrupt. */
56 
57 inline string KTDSTATE[struct thread * td] = \
58 	(((td)->td_inhibitors & TDI_SLEEPING) != 0 ? "sleep"  :		\
59 	((td)->td_inhibitors & TDI_SUSPENDED) != 0 ? "suspended" :	\
60 	((td)->td_inhibitors & TDI_SWAPPED) != 0 ? "swapped" :		\
61 	((td)->td_inhibitors & TDI_LOCK) != 0 ? "blocked" :		\
62 	((td)->td_inhibitors & TDI_IWAIT) != 0 ? "iwait" : "yielding");
63 
64 /*
65  * NOCPU changed from 255 to -1 at some point.  This hacky test will work on a
66  * kernel compiled with either version.
67  */
68 inline int is_nocpu[int cpu] = cpu < 0 || cpu > `mp_maxid;
69 
70 sched:::load-change
71 / is_nocpu[args[0]] /
72 {
73 	printf("%d %d KTRGRAPH group:\"load\", id:\"global load\", counter:\"%d\", attributes: \"none\"\n", cpu, timestamp, args[1]);
74 }
75 
76 sched:::load-change
77 / !is_nocpu[args[0]] /
78 {
79 	printf("%d %d KTRGRAPH group:\"load\", id:\"CPU %d load\", counter:\"%d\", attributes: \"none\"\n", cpu, timestamp, args[0], args[1]);
80 
81 }
82 
83 proc:::exit
84 {
85 	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);
86 }
87 
88 proc:::lwp-exit
89 {
90 	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);
91 }
92 
93 sched:::change-pri
94 {
95 	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);
96 }
97 
98 sched:::lend-pri
99 {
100 	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);
101 }
102 
103 sched:::enqueue
104 {
105 	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);
106 	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);
107 }
108 
109 sched:::dequeue
110 {
111 	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);
112 }
113 
114 sched:::tick
115 {
116 	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);
117 }
118 
119 sched:::off-cpu
120 / curthread->td_flags & TDF_IDLETD /
121 {
122 	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);
123 }
124 
125 sched:::off-cpu
126 / (curthread->td_flags & TDF_IDLETD) == 0 /
127 {
128 	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)");
129 }
130 
131 sched:::on-cpu
132 {
133 	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);
134 }
135 
136