1#!/usr/local/bin/python 2 3# Copyright (c) 2002-2003, Jeffrey Roberson <jeff@freebsd.org> 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: --- 10 unchanged lines hidden (view full) --- 19# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26# |
27# $FreeBSD: head/tools/sched/schedgraph.py 166209 2007-01-24 21:19:56Z jeff $ |
28 29import sys 30import re 31from Tkinter import * 32 33# To use: 34# - Install the ports/x11-toolkits/py-tkinter package. 35# - Add KTR_SCHED to KTR_COMPILE and KTR_MASK in your KERNCONF --- 23 unchanged lines hidden (view full) --- 59 return (str(ticks) + "ms") 60 ticks /= 1000 61 return (str(ticks) + "s") 62 63class Scaler(Frame): 64 def __init__(self, master, target): 65 Frame.__init__(self, master) 66 self.scale = Scale(self, command=self.scaleset, |
67 from_=1000, to_=10000000, orient=HORIZONTAL, 68 resolution=1000) |
69 self.label = Label(self, text="Ticks per pixel") 70 self.label.pack(side=LEFT) 71 self.scale.pack(fill="both", expand=1) 72 self.target = target 73 self.scale.set(target.scaleget()) 74 self.initialized = 1 75 76 def scaleset(self, value): --- 329 unchanged lines hidden (view full) --- 406 skipped = next 407 next.skipself = 1 408 next.real = 0 409 next = next.nextstate() 410 if (next == None): 411 next = skipped 412 self.skipnext -= 1 413 self.duration = next.timestamp - self.timestamp |
414 if (self.duration < 0): 415 self.duration = 0 416 print "Unsynchronized timestamp" 417 print self.cpu, self.timestamp 418 print next.cpu, next.timestamp |
419 delta = self.duration / canvas.ratio 420 l = canvas.create_rectangle(xpos, ypos, 421 xpos + delta, ypos - 10, fill=self.color, width=0, 422 tags=("all", "state", "event") + (self.name,)) 423 canvas.events[l] = self 424 self.item = l 425 if (self.enabled == 0): 426 canvas.itemconfigure(l, state="hidden") --- 387 unchanged lines hidden (view full) --- 814 return (80) 815 816 def yscale(self): 817 return (self.ysize() / Counter.max) 818 819 820class KTRFile: 821 def __init__(self, file): |
822 self.timestamp_first = {} 823 self.timestamp_last = {} 824 self.timestamp_adjust = {} 825 self.timestamp_f = None 826 self.timestamp_l = None |
827 self.lineno = -1 828 self.threads = [] 829 self.sources = [] 830 self.ticks = {} 831 self.load = {} 832 self.crit = {} |
833 self.stathz = 0 |
834 835 self.parse(file) 836 self.fixup() 837 global ticksps |
838 print "first", self.timestamp_f, "last", self.timestamp_l 839 print "time span", self.timespan() |
840 print "stathz", self.stathz |
841 ticksps = self.ticksps() 842 print "Ticks per second", ticksps |
843 844 def parse(self, file): 845 try: 846 ifp = open(file) 847 except: 848 print "Can't open", file 849 sys.exit(1) 850 --- 50 unchanged lines hidden (view full) --- 901 [sched_prio_re, self.sched_prio], 902 [preempted_re, self.preempted], 903 [sched_rem_re, self.sched_rem], 904 [sched_exit_re, self.sched_exit], 905 [sched_clock_re, self.sched_clock], 906 [critsec_re, self.critsec], 907 [idled_re, self.idled]] 908 |
909 lines = ifp.readlines() 910 self.synchstamp(lines) 911 for line in lines: |
912 self.lineno += 1 913 if ((self.lineno % 1024) == 0): 914 status.startup("Parsing line " + 915 str(self.lineno)) 916 for p in parsers: 917 m = p[0].match(line) 918 if (m != None): 919 p[1](*m.groups()) 920 break 921 # if (m == None): 922 # print line, 923 |
924 def synchstamp(self, lines): 925 status.startup("Rationalizing Timestamps") 926 tstamp_re = re.compile("\s+\d+\s+(\d+)\s+(\d+)\s+.*") 927 for line in lines: 928 m = tstamp_re.match(line) 929 if (m != None): 930 self.addstamp(*m.groups()) 931 self.pickstamp() 932 self.monostamp(lines) 933 934 935 def monostamp(self, lines): 936 laststamp = None 937 tstamp_re = re.compile("\s+\d+\s+(\d+)\s+(\d+)\s+.*") 938 for line in lines: 939 m = tstamp_re.match(line) 940 if (m == None): 941 continue 942 (cpu, timestamp) = m.groups() 943 timestamp = int(timestamp) 944 cpu = int(cpu) 945 timestamp -= self.timestamp_adjust[cpu] 946 if (laststamp != None and timestamp > laststamp): 947 self.timestamp_adjust[cpu] += timestamp - laststamp 948 laststamp = timestamp 949 950 def addstamp(self, cpu, timestamp): |
951 timestamp = int(timestamp) |
952 cpu = int(cpu) 953 try: 954 if (timestamp > self.timestamp_first[cpu]): 955 return 956 except: 957 self.timestamp_first[cpu] = timestamp 958 self.timestamp_last[cpu] = timestamp 959 960 def pickstamp(self): 961 base = self.timestamp_last[0] 962 for i in range(0, len(self.timestamp_last)): 963 if (self.timestamp_last[i] < base): 964 base = self.timestamp_last[i] 965 966 print "Adjusting to base stamp", base 967 for i in range(0, len(self.timestamp_last)): 968 self.timestamp_adjust[i] = self.timestamp_last[i] - base; 969 print "CPU ", i, "adjust by ", self.timestamp_adjust[i] 970 971 self.timestamp_f = 0 972 for i in range(0, len(self.timestamp_first)): 973 first = self.timestamp_first[i] - self.timestamp_adjust[i] 974 if (first > self.timestamp_f): 975 self.timestamp_f = first 976 977 self.timestamp_l = 0 978 for i in range(0, len(self.timestamp_last)): 979 last = self.timestamp_last[i] - self.timestamp_adjust[i] 980 if (last > self.timestamp_l): 981 self.timestamp_l = last 982 983 984 def checkstamp(self, cpu, timestamp): 985 cpu = int(cpu) 986 timestamp = int(timestamp) 987 if (timestamp > self.timestamp_first[cpu]): |
988 print "Bad timestamp on line ", self.lineno 989 return (0) |
990 timestamp -= self.timestamp_adjust[cpu] 991 return (timestamp) |
992 993 def timespan(self): |
994 return (self.timestamp_f - self.timestamp_l); |
995 996 def ticksps(self): 997 return (self.timespan() / self.ticks[0]) * int(self.stathz) 998 999 def switchout(self, cpu, timestamp, td, pcomm, prio, inhibit, wmesg, lock): 1000 TDI_SUSPENDED = 0x0001 1001 TDI_SLEEPING = 0x0002 1002 TDI_SWAPPED = 0x0004 1003 TDI_LOCK = 0x0008 1004 TDI_IWAIT = 0x0010 1005 |
1006 timestamp = self.checkstamp(cpu, timestamp) 1007 if (timestamp == 0): |
1008 return 1009 inhibit = int(inhibit) 1010 thread = self.findtd(td, pcomm) 1011 if (inhibit & TDI_SWAPPED): 1012 Swapped(thread, cpu, timestamp, prio) 1013 elif (inhibit & TDI_SLEEPING): 1014 Sleep(thread, cpu, timestamp, prio, wmesg) 1015 elif (inhibit & TDI_LOCK): --- 4 unchanged lines hidden (view full) --- 1020 Suspended(thread, cpu, timestamp, prio) 1021 elif (inhibit == 0): 1022 Yielding(thread, cpu, timestamp, prio) 1023 else: 1024 print "Unknown event", inhibit 1025 sys.exit(1) 1026 1027 def idled(self, cpu, timestamp, td, pcomm, prio): |
1028 timestamp = self.checkstamp(cpu, timestamp) 1029 if (timestamp == 0): |
1030 return 1031 thread = self.findtd(td, pcomm) 1032 Idle(thread, cpu, timestamp, prio) 1033 1034 def preempted(self, cpu, timestamp, td, pcomm, prio, bytd, bypcomm): |
1035 timestamp = self.checkstamp(cpu, timestamp) 1036 if (timestamp == 0): |
1037 return 1038 thread = self.findtd(td, pcomm) 1039 Preempted(thread, cpu, timestamp, prio, 1040 self.findtd(bytd, bypcomm)) 1041 1042 def switchin(self, cpu, timestamp, td, pcomm, prio): |
1043 timestamp = self.checkstamp(cpu, timestamp) 1044 if (timestamp == 0): |
1045 return 1046 thread = self.findtd(td, pcomm) 1047 Running(thread, cpu, timestamp, prio) 1048 1049 def sched_add(self, cpu, timestamp, td, pcomm, prio, bytd, bypcomm): |
1050 timestamp = self.checkstamp(cpu, timestamp) 1051 if (timestamp == 0): |
1052 return 1053 thread = self.findtd(td, pcomm) 1054 bythread = self.findtd(bytd, bypcomm) 1055 Runq(thread, cpu, timestamp, prio, bythread) 1056 Wokeup(bythread, cpu, timestamp, thread) 1057 1058 def sched_rem(self, cpu, timestamp, td, pcomm, prio, bytd, bypcomm): |
1059 timestamp = self.checkstamp(cpu, timestamp) 1060 if (timestamp == 0): |
1061 return 1062 thread = self.findtd(td, pcomm) 1063 KsegrpRunq(thread, cpu, timestamp, prio, 1064 self.findtd(bytd, bypcomm)) 1065 1066 def sched_exit(self, cpu, timestamp, td, pcomm, prio): |
1067 timestamp = self.checkstamp(cpu, timestamp) 1068 if (timestamp == 0): |
1069 return 1070 thread = self.findtd(td, pcomm) 1071 Sched_exit(thread, cpu, timestamp, prio) 1072 1073 def sched_clock(self, cpu, timestamp, td, pcomm, prio, stathz): |
1074 timestamp = self.checkstamp(cpu, timestamp) 1075 if (timestamp == 0): |
1076 return 1077 self.stathz = stathz 1078 cpu = int(cpu) 1079 try: 1080 ticks = self.ticks[cpu] 1081 except: 1082 self.ticks[cpu] = 0 1083 self.ticks[cpu] += 1 1084 thread = self.findtd(td, pcomm) 1085 Tick(thread, cpu, timestamp, prio, stathz) 1086 1087 def sched_prio(self, cpu, timestamp, td, pcomm, prio, newprio, bytd, bypcomm): 1088 if (prio == newprio): 1089 return |
1090 timestamp = self.checkstamp(cpu, timestamp) 1091 if (timestamp == 0): |
1092 return 1093 thread = self.findtd(td, pcomm) 1094 bythread = self.findtd(bytd, bypcomm) 1095 Prio(thread, cpu, timestamp, prio, newprio, bythread) 1096 Lend(bythread, cpu, timestamp, newprio, thread) 1097 1098 def cpuload(self, cpu, timestamp, count): |
1099 timestamp = self.checkstamp(cpu, timestamp) 1100 if (timestamp == 0): |
1101 return 1102 cpu = int(cpu) 1103 try: 1104 load = self.load[cpu] 1105 except: 1106 load = Counter("cpu" + str(cpu) + " load") 1107 self.load[cpu] = load 1108 self.sources.insert(0, load) 1109 Count(load, cpu, timestamp, count) 1110 1111 def loadglobal(self, cpu, timestamp, count): |
1112 timestamp = self.checkstamp(cpu, timestamp) 1113 if (timestamp == 0): |
1114 return 1115 cpu = 0 1116 try: 1117 load = self.load[cpu] 1118 except: 1119 load = Counter("CPU load") 1120 self.load[cpu] = load 1121 self.sources.insert(0, load) 1122 Count(load, cpu, timestamp, count) 1123 1124 def critsec(self, cpu, timestamp, td, pcomm, to): |
1125 timestamp = self.checkstamp(cpu, timestamp) 1126 if (timestamp == 0): |
1127 return 1128 cpu = int(cpu) 1129 try: 1130 crit = self.crit[cpu] 1131 except: 1132 crit = Counter("Critical Section") 1133 self.crit[cpu] = crit 1134 self.sources.insert(0, crit) --- 5 unchanged lines hidden (view full) --- 1140 return thread 1141 thread = Thread(td, pcomm) 1142 self.threads.append(thread) 1143 self.sources.append(thread) 1144 return (thread) 1145 1146 def fixup(self): 1147 for source in self.sources: |
1148 Padevent(source, -1, self.timestamp_l) 1149 Padevent(source, -1, self.timestamp_f, last=1) |
1150 source.fixup() 1151 1152class SchedDisplay(Canvas): 1153 def __init__(self, master): 1154 self.ratio = 1 1155 self.ktrfile = None 1156 self.sources = None 1157 self.bdheight = 10 --- 178 unchanged lines hidden --- |