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