- Add a horrible bit of code to detect tsc differences between processors.

This only works if there is no significant drift and all processors are
   running at the same frequency.  Fortunately, schedgraph traces on MP
   machines tend to cover less than a second so drift shouldn't be an issue.
 - KTRFile::synchstamp() iterates once over the whole list to determine the
   lowest tsc value and syncs adjusts all other values to match.  We assume
   that the first tick recorded on all cpus happened at the same instant to
   start with.
 - KTRFile::monostamp() iterates again over the whole file and checks for
   a cpu agnostic monotonically increasing clock.  If the time ever goes
   backwards the cpu responsible is adjusted further to fit.  This will
   make the possible incorrect delta between cpus as small as the shortest
   time between two events.  This time can be fairly large due to sched_lock
   essentially protecting all events.
 - KTRFile::checkstamp() now returns an adjusted timestamp.
 - StateEvent::draw() detects states that occur out of order in time and
   draws them as 0 pixels after printing a warning.
This commit is contained in:
jeff 2007-01-24 21:19:56 +00:00
parent 743ea48fbc
commit 04228656e7

View File

@ -64,7 +64,8 @@ class Scaler(Frame):
def __init__(self, master, target):
Frame.__init__(self, master)
self.scale = Scale(self, command=self.scaleset,
from_=1000, to_=1000000, orient=HORIZONTAL, resolution=1000)
from_=1000, to_=10000000, orient=HORIZONTAL,
resolution=1000)
self.label = Label(self, text="Ticks per pixel")
self.label.pack(side=LEFT)
self.scale.pack(fill="both", expand=1)
@ -410,6 +411,11 @@ def draw(self, canvas, xpos, ypos):
next = skipped
self.skipnext -= 1
self.duration = next.timestamp - self.timestamp
if (self.duration < 0):
self.duration = 0
print "Unsynchronized timestamp"
print self.cpu, self.timestamp
print next.cpu, next.timestamp
delta = self.duration / canvas.ratio
l = canvas.create_rectangle(xpos, ypos,
xpos + delta, ypos - 10, fill=self.color, width=0,
@ -813,22 +819,27 @@ def yscale(self):
class KTRFile:
def __init__(self, file):
self.timestamp_first = None
self.timestamp_last = None
self.timestamp_first = {}
self.timestamp_last = {}
self.timestamp_adjust = {}
self.timestamp_f = None
self.timestamp_l = None
self.lineno = -1
self.threads = []
self.sources = []
self.ticks = {}
self.load = {}
self.crit = {}
self.stathz = 0
self.parse(file)
self.fixup()
global ticksps
ticksps = self.ticksps()
print "Ticks per second", ticksps, "timespan", self.timespan()
print "first", self.timestamp_f, "last", self.timestamp_l
print "time span", self.timespan()
print "stathz", self.stathz
print "first", self.timestamp_first, "last", self.timestamp_last
ticksps = self.ticksps()
print "Ticks per second", ticksps
def parse(self, file):
try:
@ -895,7 +906,9 @@ def parse(self, file):
[critsec_re, self.critsec],
[idled_re, self.idled]]
for line in ifp.readlines():
lines = ifp.readlines()
self.synchstamp(lines)
for line in lines:
self.lineno += 1
if ((self.lineno % 1024) == 0):
status.startup("Parsing line " +
@ -908,18 +921,77 @@ def parse(self, file):
# if (m == None):
# print line,
def checkstamp(self, timestamp):
def synchstamp(self, lines):
status.startup("Rationalizing Timestamps")
tstamp_re = re.compile("\s+\d+\s+(\d+)\s+(\d+)\s+.*")
for line in lines:
m = tstamp_re.match(line)
if (m != None):
self.addstamp(*m.groups())
self.pickstamp()
self.monostamp(lines)
def monostamp(self, lines):
laststamp = None
tstamp_re = re.compile("\s+\d+\s+(\d+)\s+(\d+)\s+.*")
for line in lines:
m = tstamp_re.match(line)
if (m == None):
continue
(cpu, timestamp) = m.groups()
timestamp = int(timestamp)
cpu = int(cpu)
timestamp -= self.timestamp_adjust[cpu]
if (laststamp != None and timestamp > laststamp):
self.timestamp_adjust[cpu] += timestamp - laststamp
laststamp = timestamp
def addstamp(self, cpu, timestamp):
timestamp = int(timestamp)
if (self.timestamp_first == None):
self.timestamp_first = timestamp
if (timestamp > self.timestamp_first):
cpu = int(cpu)
try:
if (timestamp > self.timestamp_first[cpu]):
return
except:
self.timestamp_first[cpu] = timestamp
self.timestamp_last[cpu] = timestamp
def pickstamp(self):
base = self.timestamp_last[0]
for i in range(0, len(self.timestamp_last)):
if (self.timestamp_last[i] < base):
base = self.timestamp_last[i]
print "Adjusting to base stamp", base
for i in range(0, len(self.timestamp_last)):
self.timestamp_adjust[i] = self.timestamp_last[i] - base;
print "CPU ", i, "adjust by ", self.timestamp_adjust[i]
self.timestamp_f = 0
for i in range(0, len(self.timestamp_first)):
first = self.timestamp_first[i] - self.timestamp_adjust[i]
if (first > self.timestamp_f):
self.timestamp_f = first
self.timestamp_l = 0
for i in range(0, len(self.timestamp_last)):
last = self.timestamp_last[i] - self.timestamp_adjust[i]
if (last > self.timestamp_l):
self.timestamp_l = last
def checkstamp(self, cpu, timestamp):
cpu = int(cpu)
timestamp = int(timestamp)
if (timestamp > self.timestamp_first[cpu]):
print "Bad timestamp on line ", self.lineno
return (0)
self.timestamp_last = timestamp
return (1)
timestamp -= self.timestamp_adjust[cpu]
return (timestamp)
def timespan(self):
return (self.timestamp_first - self.timestamp_last);
return (self.timestamp_f - self.timestamp_l);
def ticksps(self):
return (self.timespan() / self.ticks[0]) * int(self.stathz)
@ -931,7 +1003,8 @@ def switchout(self, cpu, timestamp, td, pcomm, prio, inhibit, wmesg, lock):
TDI_LOCK = 0x0008
TDI_IWAIT = 0x0010
if (self.checkstamp(timestamp) == 0):
timestamp = self.checkstamp(cpu, timestamp)
if (timestamp == 0):
return
inhibit = int(inhibit)
thread = self.findtd(td, pcomm)
@ -952,26 +1025,30 @@ def switchout(self, cpu, timestamp, td, pcomm, prio, inhibit, wmesg, lock):
sys.exit(1)
def idled(self, cpu, timestamp, td, pcomm, prio):
if (self.checkstamp(timestamp) == 0):
timestamp = self.checkstamp(cpu, timestamp)
if (timestamp == 0):
return
thread = self.findtd(td, pcomm)
Idle(thread, cpu, timestamp, prio)
def preempted(self, cpu, timestamp, td, pcomm, prio, bytd, bypcomm):
if (self.checkstamp(timestamp) == 0):
timestamp = self.checkstamp(cpu, timestamp)
if (timestamp == 0):
return
thread = self.findtd(td, pcomm)
Preempted(thread, cpu, timestamp, prio,
self.findtd(bytd, bypcomm))
def switchin(self, cpu, timestamp, td, pcomm, prio):
if (self.checkstamp(timestamp) == 0):
timestamp = self.checkstamp(cpu, timestamp)
if (timestamp == 0):
return
thread = self.findtd(td, pcomm)
Running(thread, cpu, timestamp, prio)
def sched_add(self, cpu, timestamp, td, pcomm, prio, bytd, bypcomm):
if (self.checkstamp(timestamp) == 0):
timestamp = self.checkstamp(cpu, timestamp)
if (timestamp == 0):
return
thread = self.findtd(td, pcomm)
bythread = self.findtd(bytd, bypcomm)
@ -979,20 +1056,23 @@ def sched_add(self, cpu, timestamp, td, pcomm, prio, bytd, bypcomm):
Wokeup(bythread, cpu, timestamp, thread)
def sched_rem(self, cpu, timestamp, td, pcomm, prio, bytd, bypcomm):
if (self.checkstamp(timestamp) == 0):
timestamp = self.checkstamp(cpu, timestamp)
if (timestamp == 0):
return
thread = self.findtd(td, pcomm)
KsegrpRunq(thread, cpu, timestamp, prio,
self.findtd(bytd, bypcomm))
def sched_exit(self, cpu, timestamp, td, pcomm, prio):
if (self.checkstamp(timestamp) == 0):
timestamp = self.checkstamp(cpu, timestamp)
if (timestamp == 0):
return
thread = self.findtd(td, pcomm)
Sched_exit(thread, cpu, timestamp, prio)
def sched_clock(self, cpu, timestamp, td, pcomm, prio, stathz):
if (self.checkstamp(timestamp) == 0):
timestamp = self.checkstamp(cpu, timestamp)
if (timestamp == 0):
return
self.stathz = stathz
cpu = int(cpu)
@ -1007,7 +1087,8 @@ def sched_clock(self, cpu, timestamp, td, pcomm, prio, stathz):
def sched_prio(self, cpu, timestamp, td, pcomm, prio, newprio, bytd, bypcomm):
if (prio == newprio):
return
if (self.checkstamp(timestamp) == 0):
timestamp = self.checkstamp(cpu, timestamp)
if (timestamp == 0):
return
thread = self.findtd(td, pcomm)
bythread = self.findtd(bytd, bypcomm)
@ -1015,7 +1096,8 @@ def sched_prio(self, cpu, timestamp, td, pcomm, prio, newprio, bytd, bypcomm):
Lend(bythread, cpu, timestamp, newprio, thread)
def cpuload(self, cpu, timestamp, count):
if (self.checkstamp(timestamp) == 0):
timestamp = self.checkstamp(cpu, timestamp)
if (timestamp == 0):
return
cpu = int(cpu)
try:
@ -1027,7 +1109,8 @@ def cpuload(self, cpu, timestamp, count):
Count(load, cpu, timestamp, count)
def loadglobal(self, cpu, timestamp, count):
if (self.checkstamp(timestamp) == 0):
timestamp = self.checkstamp(cpu, timestamp)
if (timestamp == 0):
return
cpu = 0
try:
@ -1039,7 +1122,8 @@ def loadglobal(self, cpu, timestamp, count):
Count(load, cpu, timestamp, count)
def critsec(self, cpu, timestamp, td, pcomm, to):
if (self.checkstamp(timestamp) == 0):
timestamp = self.checkstamp(cpu, timestamp)
if (timestamp == 0):
return
cpu = int(cpu)
try:
@ -1061,8 +1145,8 @@ def findtd(self, td, pcomm):
def fixup(self):
for source in self.sources:
Padevent(source, -1, self.timestamp_last)
Padevent(source, -1, self.timestamp_first, last=1)
Padevent(source, -1, self.timestamp_l)
Padevent(source, -1, self.timestamp_f, last=1)
source.fixup()
class SchedDisplay(Canvas):