summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClark Williams <williams@redhat.com>2009-06-12 13:20:17 -0500
committerClark Williams <williams@redhat.com>2009-06-12 13:20:17 -0500
commit3e04327f7fc0be0ee2cb3d8157a4faf43e4b00cb (patch)
tree2c71e3a9a975ce1f829a6244b4284e01cea014e5
parentc7deee8c38a08e173a5e5282280c2abb362c9370 (diff)
parent11f68bd172b13866666837fc9534c0f7b5eb338e (diff)
downloadrt-tests-3e04327f7fc0be0ee2cb3d8157a4faf43e4b00cb.tar.gz
rt-tests-3e04327f7fc0be0ee2cb3d8157a4faf43e4b00cb.tar.xz
merge resolutionv0.41
-rw-r--r--.gitignore2
-rw-r--r--Makefile15
-rw-r--r--rt-tests.spec-in4
-rw-r--r--src/cyclictest/cyclictest.c12
-rw-r--r--src/hwlatdetect/hwlat.txt (renamed from src/smidetect/smi_detector.txt)16
-rw-r--r--src/hwlatdetect/hwlatdetect.8 (renamed from src/smidetect/smidetect.8)16
-rwxr-xr-xsrc/hwlatdetect/hwlatdetect.py356
-rw-r--r--src/smidetect/smidetect.py352
8 files changed, 392 insertions, 381 deletions
diff --git a/.gitignore b/.gitignore
index d257801..67d4857 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,5 @@ classic_pi
pi_stress
cyclictest
signaltest
+rt-tests.spec
+smidetect
diff --git a/Makefile b/Makefile
index ef3bd6d..4018d5a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
-VERSION_STRING = "0.40"
+VERSION_STRING = 0.41
-TARGETS = cyclictest signaltest classic_pi pi_stress smidetect
+TARGETS = cyclictest signaltest classic_pi pi_stress hwlatdetect
FLAGS = -Wall -Wno-nonnull -O2
LIBS = -lpthread -lrt
DESTDIR ?=
@@ -22,18 +22,19 @@ classic_pi: src/pi_tests/classic_pi.c
pi_stress: src/pi_tests/pi_stress.c
$(CC) $(FLAGS) -D_GNU_SOURCE -D VERSION_STRING=\"$(VERSION_STRING)\" $^ -o $@ $(LIBS)
-smidetect: src/smidetect/smidetect.py
- cp src/smidetect/smidetect.py smidetect
- chmod +x smidetect
+hwlatdetect: src/hwlatdetect/hwlatdetect.py
+ chmod +x src/hwlatdetect/hwlatdetect.py
+ ln -s src/hwlatdetect/hwlatdetect.py hwlatdetect
CLEANUP = $(TARGETS) *.o .depend *.*~ *.orig *.rej rt-tests.spec
CLEANUP += $(if $(wildcard .git), ChangeLog)
clean:
for F in $(CLEANUP); do find -type f -name $$F | xargs rm -f; done
+ rm -f hwlatdetect
distclean: clean
- rm -rf BUILD RPMS SRPMS releases
+ rm -rf BUILD RPMS SRPMS releases *.tar.gz rt-tests.spec
changelog:
git log >ChangeLog
@@ -43,7 +44,7 @@ install: all
cp $(TARGETS) "$(DESTDIR)$(bindir)"
gzip src/cyclictest/cyclictest.8 -c >"$(DESTDIR)$(mandir)/cyclictest.8.gz"
gzip src/pi_tests/pi_stress.8 -c >"$(DESTDIR)$(mandir)/pi_stress.8.gz"
- gzip src/smidetect/smidetect.8 -c >"$(DESTDIR)$(mandir)/smidetect.8.gz"
+ gzip src/hwlatdetect/hwlatdetect.8 -c >"$(DESTDIR)$(mandir)/hwlatdetect.8.gz"
release: clean changelog
mkdir -p releases
diff --git a/rt-tests.spec-in b/rt-tests.spec-in
index ad8e434..56feeb9 100644
--- a/rt-tests.spec-in
+++ b/rt-tests.spec-in
@@ -41,6 +41,10 @@ rm -rf $RPM_BUILD_ROOT
/usr/share/man/man8/smidetect.8.gz
%changelog
+* Thu May 28 2009 Clark Williams <williams@redhat.com> - 0.41-1
+- added Stefan Agner's patch to fix calculating time difference
+ when delta is bigger than 2147 seconds
+
* Wed May 13 2009 Clark Williams <williams@redhat.com> - 0.40-1
- added smidetect
diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c
index 558091e..3e2d500 100644
--- a/src/cyclictest/cyclictest.c
+++ b/src/cyclictest/cyclictest.c
@@ -287,18 +287,18 @@ static inline void tsnorm(struct timespec *ts)
}
}
-static inline long calcdiff(struct timespec t1, struct timespec t2)
+static inline long long calcdiff(struct timespec t1, struct timespec t2)
{
- long diff;
- diff = USEC_PER_SEC * ((int) t1.tv_sec - (int) t2.tv_sec);
+ long long diff;
+ diff = USEC_PER_SEC * (long long)((int) t1.tv_sec - (int) t2.tv_sec);
diff += ((int) t1.tv_nsec - (int) t2.tv_nsec) / 1000;
return diff;
}
-static inline long calcdiff_ns(struct timespec t1, struct timespec t2)
+static inline long long calcdiff_ns(struct timespec t1, struct timespec t2)
{
- long diff;
- diff = NSEC_PER_SEC * ((int) t1.tv_sec - (int) t2.tv_sec);
+ long long diff;
+ diff = NSEC_PER_SEC * (long long)((int) t1.tv_sec - (int) t2.tv_sec);
diff += ((int) t1.tv_nsec - (int) t2.tv_nsec);
return diff;
}
diff --git a/src/smidetect/smi_detector.txt b/src/hwlatdetect/hwlat.txt
index 411bedc..11dc067 100644
--- a/src/smidetect/smi_detector.txt
+++ b/src/hwlatdetect/hwlat.txt
@@ -1,7 +1,7 @@
Introduction:
-------------
-The module smi_detector is a special purpose kernel module that is
+The module hwlat is a special purpose kernel module that is
used to detect if System Management Interrupts (SMIs) are causing event
latencies in the Linux RT kernel.
@@ -27,17 +27,17 @@ hardware platform has a problem with long SMI service routines.
Usage:
------
-Loading the module smi_detector passing the parameter "enabled=1" is the only
-step required to start the smi_detector. It is possible to define a threshold
+Loading the module hwlat passing the parameter "enabled=1" is the only
+step required to start the hwlat. It is possible to define a threshold
in microseconds (us) above which latency spikes will be taken in account
(parameter "threshold=").
Example:
- # insmod ./smi_detector.ko enabled=1 threshold=100
+ # insmod ./hwlat.ko enabled=1 threshold=100
-After the module is loaded, it creates a directory named "smi_detector" under
-the debugfs mountpoint, "/debugfs/smi_detector" for this text. It is necessary
+After the module is loaded, it creates a directory named "hwlat" under
+the debugfs mountpoint, "/debugfs/hwlat" for this text. It is necessary
to have debugfs mounted.
avg_smi_interval_us - average interval (usecs) between SMI latency spikes
@@ -50,7 +50,7 @@ sample_us - last sample (usecs). Continously updated, may be used
smi_count - how many latency spikes have been observed
- # cd /debugfs/smi_detector
+ # cd /debugfs/hwlat
# cat *
0 (avg_smi_interval_us)
@@ -96,7 +96,7 @@ Python Script
A python script is provided in in the kernel scripts directory named
'smidetect'. This script handles mounting/unmounting the debugfs,
-loading/unloading the smi_detector module, setting various parameters
+loading/unloading the hwlat module, setting various parameters
for the SMI detector and then starting and stopping the detection. The
smidetect script handles the following arguments:
diff --git a/src/smidetect/smidetect.8 b/src/hwlatdetect/hwlatdetect.8
index b3bd2b3..0f1751e 100644
--- a/src/smidetect/smidetect.8
+++ b/src/hwlatdetect/hwlatdetect.8
@@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*-
-.TH SMIDETECT 8 "May 12, 2009"
+.TH HWLATDETECT 8 "May 12, 2009"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
@@ -13,21 +13,21 @@
.\" .sp <n> insert n+1 empty lines
.\" for manpage-specific macros, see man(7)
.SH NAME
-smidetect \- program to control the kernel SMI detection module
+hwlatdetect \- program to control the kernel SMI detection module
.SH SYNOPSIS
-.B smidetect
+.B hwlatdetect
.RI "[ \-\-duration=<time> ] [\-\-threshold=<usecs> ] \
[\-\-interval=<msecs> ] [\-\-sample_width=<msecs> ] [\-\-report=<path> ] \
[\-\-cleanup ] [\-\-debug ] [\-\-quiet ]
.\" .SH DESCRIPTION
.\" This manual page documents briefly the
-.\" .B smidetect commands.
+.\" .B hwlatdetect commands.
.\" .PP
.\" \fI<whatever>\fP escape sequences to invode bold face and italics, respectively.
-.\" \fBsmidetect\fP is a program that...
+.\" \fBhwlatdetect\fP is a program that...
.SH DESCRIPTION
-\fBsmidetect\fP is a program that controls the SMI detector kernel
+\fBhwlatdetect\fP is a program that controls the SMI detector kernel
module (smi_detector.ko), provided with a realtime Linux kernel. The
module is used to detect the presence of System Management Interrupts
(SMI) which in some cases cause unexplained latencies. SMIs are generally
@@ -81,5 +81,5 @@ Turn off all information prints
.\" .IR "The Rise and Fall of a Fooish Bar" ,
.\" available via the Info system.
.SH AUTHOR
-.B smidetect
-was written by Clark Williams <williams@redhat.com>
+.B hwlatdetect
+.R was written by Clark Williams <williams@redhat.com>
diff --git a/src/hwlatdetect/hwlatdetect.py b/src/hwlatdetect/hwlatdetect.py
new file mode 100755
index 0000000..30798c3
--- /dev/null
+++ b/src/hwlatdetect/hwlatdetect.py
@@ -0,0 +1,356 @@
+#!/usr/bin/python
+
+import sys
+import os
+import time
+import subprocess
+import errno
+
+version = "0.5"
+debugging = False
+quiet = False
+
+def debug(str):
+ if debugging: print(str)
+
+def info(str):
+ if not quiet: print(str)
+
+#
+# Class used to manage mounting and umounting the debugfs
+# filesystem. Note that if an instance of this class mounts
+# the debufs, it will unmount when cleaning up, but if it
+# discovers that debugfs is already mounted, it will leave
+# it mounted.
+#
+class DebugFS(object):
+ '''class to manage mounting/umounting the debugfs'''
+ def __init__(self):
+ self.premounted = False
+ self.mounted = False
+ self.mountpoint = ''
+ f = open('/proc/mounts')
+ for l in f:
+ field = l.split()
+ if field[2] == "debugfs":
+ self.premounted = True
+ self.mountpoint = field[1]
+ break
+ f.close()
+
+ def mount(self, path='/sys/kernel/debug'):
+ if self.premounted or self.mounted:
+ debug("not mounting debugfs")
+ return True
+ debug("mounting debugfs at %s" % path)
+ self.mountpoint = path
+ cmd = ['/bin/mount', '-t', 'debugfs', 'none', path]
+ self.mounted = (subprocess.call(cmd) == 0)
+ if not self.mounted:
+ raise RuntimeError, "Failed to mount debugfs"
+ return self.mounted
+
+ def umount(self):
+ if self.premounted or not self.mounted:
+ debug("not umounting debugfs")
+ return True
+ debug("umounting debugfs")
+ cmd = ['/bin/umount', self.mountpoint]
+ self.mounted = not (subprocess.call(cmd) == 0)
+ if self.mounted:
+ raise RuntimeError, "Failed to umount debugfs"
+ return not self.mounted
+
+ def getval(self, item, nonblocking=False):
+ path = os.path.join(self.mountpoint, item)
+ if nonblocking == False:
+ f = open(path)
+ val = f.readline()
+ f.close()
+ else:
+ fd = os.open(path, os.O_RDONLY|os.O_NONBLOCK)
+ try:
+ val = os.read(fd, 256)
+ except OSError, e:
+ if e.errno == errno.EAGAIN:
+ val = None
+ else:
+ raise
+ os.close(fd)
+ return val
+
+ def putval(self, item, value):
+ path = os.path.join(self.mountpoint, item)
+ f = open(path, "w")
+ f.write(str(value))
+ f.flush()
+ f.close()
+
+ def getpath(self, item):
+ return os.path.join(self.mountpoint, item)
+
+#
+# Class used to manage loading and unloading of the
+# hwlat kernel module. Like the debugfs class
+# above, if the module is already loaded, this class will
+# leave it alone when cleaning up.
+#
+class Kmod(object):
+ ''' class to manage loading and unloading hwlat.ko'''
+ def __init__(self, module='hwlat_detector'):
+ self.modname = module
+ self.preloaded = False
+ f = open ('/proc/modules')
+ for l in f:
+ field = l.split()
+ if field[0] == self.modname:
+ self.preloaded = True
+ break
+ f.close
+
+ def load(self):
+ if self.preloaded:
+ debug("not loading %s (already loaded)" % self.modname)
+ return True
+ cmd = ['/sbin/modprobe', self.modname]
+ return (subprocess.call(cmd) == 0)
+
+ def unload(self):
+ if self.preloaded:
+ debug("Not unloading %s" % self.modname)
+ return True
+ cmd = ['/sbin/modprobe', '-r', self.modname]
+ return (subprocess.call(cmd) == 0)
+
+#
+# Class to simplify running the hwlat kernel module
+#
+class Hwlat(object):
+ '''class to wrap access to hwlat debugfs files'''
+ def __init__(self):
+ if os.getuid() != 0:
+ raise RuntimeError, "Must be root"
+ self.debugfs = DebugFS()
+ self.kmod = Kmod()
+ self.setup()
+ self.testduration = 10 # ten seconds
+ self.samples = []
+
+ def force_cleanup(self):
+ debug("forcing unload of hwlat module")
+ self.kmod.preloaded = False
+ debug("forcing unmount of debugfs")
+ self.debugfs.premounted = False
+ self.cleanup()
+ debug("exiting")
+ sys.exit(0)
+
+ def setup(self):
+ if not self.debugfs.mount():
+ raise RuntimeError, "Failed to mount debugfs"
+ if not self.kmod.load():
+ raise RuntimeError, "Failed to unload hwlat"
+
+ def cleanup(self):
+ if not self.kmod.unload():
+ raise RuntimeError, "Failed to unload hwlat"
+ if not self.debugfs.umount():
+ raise RuntimeError, "Failed to unmount debugfs"
+
+ def get(self, field):
+ return int(self.debugfs.getval(os.path.join("hwlat_detector", field)))
+
+ def set(self, field, val):
+ if field == "enable" and val:
+ val = 1
+ self.debugfs.putval(os.path.join("hwlat_detector", field), str(val))
+
+ def get_sample(self):
+ return self.debugfs.getval("hwlat_detector/sample", nonblocking=True)
+
+ def start(self):
+ debug("enabling hwlat module")
+ count = 0
+ self.set("enable", 1)
+ while self.get("enable") == 0:
+ count += 1
+ debug("setting enable to 1 (%d)" % count)
+ time.sleep(0.1)
+ self.set("enable", 1)
+
+ def stop(self):
+ debug("disabling hwlat module")
+ count = 0
+ self.set("enable", 0)
+ while self.get("enable") == 1:
+ count += 1
+ debug("setting enable to zero(%d)" % count)
+ time.sleep(0.1)
+ self.set("enable", 0)
+
+ def detect(self):
+ self.samples = []
+ testend = time.time() + self.testduration
+ debug("Starting hardware latency detection for %d seconds" % (self.testduration))
+ try:
+ pollcnt = 0
+ self.start()
+ try:
+ while time.time() < testend:
+ pollcnt += 1
+ val = self.get_sample()
+ if val:
+ self.samples.append(val.strip())
+ debug("got a latency sample: %s" % val.strip())
+ continue
+ time.sleep(0.1)
+ except KeyboardInterrupt, e:
+ print "interrupted"
+ sys.exit(1)
+ finally:
+ debug("Stopping hardware latency detection (poll count: %d" % pollcnt)
+ self.stop()
+ debug("Hardware latency detection done (%d samples)" % len(self.samples))
+
+def seconds(str):
+ "convert input string to value in seconds"
+ if str.isdigit():
+ return int(str)
+ elif str[-2].isalpha():
+ raise RuntimeError, "illegal suffix for seconds: '%s'" % str[-2:-1]
+ elif str[-1:] == 's':
+ return int(str[0:-1])
+ elif str[-1:] == 'm':
+ return int(str[0:-1]) * 60
+ elif str[-1:] == 'h':
+ return int(str[0:-1]) * 3600
+ elif str[-1:] == 'd':
+ return int(str[0:-1]) * 86400
+ elif str[-1:] == 'w':
+ return int(str[0:-1]) * 86400 * 7
+ else:
+ raise RuntimeError, "unknown suffix for second conversion: '%s'" % str[-1]
+
+
+def microseconds(str):
+ "convert input string to microsecond value"
+ if str[-2:] == 'ms':
+ return (int(str[0:-2]) * 1000)
+ elif str[-2:] == 'us':
+ return int(str[0:-2])
+ elif str[-1:] == 's':
+ return (int(str[0:-1]) * 1000 * 1000)
+ elif str[-1:].isalpha():
+ raise RuntimeError, "unknown suffix for microsecond conversion: '%s'" % str[-1]
+ else:
+ return int(str)
+
+if __name__ == '__main__':
+ from optparse import OptionParser
+
+ parser = OptionParser()
+ parser.add_option("--duration", default=None, type="string",
+ dest="duration",
+ help="total time to test for hardware latency (<n>{smdw})")
+
+ parser.add_option("--threshold", default=None, type="string",
+ dest="threshold",
+ help="value above which is considered an hardware latency")
+
+ parser.add_option("--window", default=None, type="string",
+ dest="window",
+ help="time between samples")
+
+ parser.add_option("--width", default=None, type="string",
+ dest="width",
+ help="time to actually measure")
+
+ parser.add_option("--report", default=None, type="string",
+ dest="report",
+ help="filename for sample data")
+
+ parser.add_option("--cleanup", action="store_true", default=False,
+ dest="cleanup",
+ help="force unload of module and umount of debugfs")
+
+ parser.add_option("--debug", action="store_true", default=False,
+ dest="debug",
+ help="turn on debugging prints")
+
+ parser.add_option("--quiet", action="store_true", default=False,
+ dest="quiet",
+ help="turn off all screen output")
+
+ (o, a) = parser.parse_args()
+
+ hwlat = Hwlat()
+
+ if o.debug:
+ debugging = True
+ quiet = False
+ debug("debugging prints turned on")
+
+ if o.quiet:
+ quiet = True
+ debugging = False
+
+ if o.cleanup:
+ debug("forcing cleanup of debugfs and hardware latency module")
+ hwlat.force_cleanup()
+ sys.exit(0)
+
+ if o.threshold:
+ t = microseconds(o.threshold)
+ hwlat.set("threshold", t)
+ debug("threshold set to %dus" % t)
+
+ if o.window:
+ w = microseconds(o.window)
+ debug("window parameter = %d" % w)
+ hwlat.set("window", w)
+ debug("window for sampling set to %dus" % w)
+
+ if o.width:
+ w = microseconds(o.width)
+ debug("width parameter = %d" % w)
+ hwlat.set("width", w)
+ debug("sample width set to %dus" % w)
+
+ if o.duration:
+ hwlat.testduration = seconds(o.duration)
+ else:
+ hwlat.testduration = 120 # 2 minutes
+ debug("test duration is %ds" % hwlat.testduration)
+
+ reportfile = o.report
+
+ info("hwlatdetect: test duration %d seconds" % hwlat.testduration)
+ info(" parameters:")
+ info(" Latency threshold: %dus" % hwlat.get("threshold"))
+ info(" Sample window: %dus" % hwlat.get("window"))
+ info(" Sample width: %dus" % hwlat.get("width"))
+ info(" Non-sampling period: %dus" % (hwlat.get("window") - hwlat.get("width")))
+ info(" Output File: %s" % reportfile)
+ info("\nStarting test")
+
+ hwlat.detect()
+
+ info("test finished")
+
+ exceeding = hwlat.get("count")
+ info("Max Latency: %dus" % hwlat.get("max"))
+ info("Samples recorded: %d" % len(hwlat.samples))
+ info("Samples exceeding threshold: %d" % exceeding)
+
+ if reportfile:
+ f = open(reportfile, "w")
+ for s in hwlat.samples:
+ f.write("%d\n" % s)
+ f.close()
+ info("sample data written to %s" % reportfile)
+ else:
+ for s in hwlat.samples:
+ print "%s" % s
+
+ hwlat.cleanup()
+ sys.exit(exceeding)
diff --git a/src/smidetect/smidetect.py b/src/smidetect/smidetect.py
deleted file mode 100644
index 23e45b9..0000000
--- a/src/smidetect/smidetect.py
+++ /dev/null
@@ -1,352 +0,0 @@
-#!/usr/bin/python
-
-import sys
-import os
-import time
-import subprocess
-
-version = "0.4"
-debugging = False
-quiet = False
-
-# defaults for parameters
-default_threshold = 100 # 100 microseconds
-default_interval = 5 # 5 milliseconds
-default_width = 20 # 20 milliseconds
-
-def debug(str):
- if debugging: print(str)
-
-def info(str):
- if not quiet: print(str)
-
-class DebugFS(object):
- '''class to manage the debugfs'''
- def __init__(self):
- self.premounted = False
- self.mounted = False
- self.mountpoint = ''
- f = open('/proc/mounts')
- for l in f:
- field = l.split()
- if field[2] == "debugfs":
- self.premounted = True
- self.mountpoint = field[1]
- break
- f.close()
-
- def mount(self, path='/sys/kernel/debug'):
- if self.premounted or self.mounted:
- return True
- self.mountpoint = path
- cmd = ['/bin/mount', '-t', 'debugfs', 'none', path]
- self.mounted = (subprocess.call(cmd) == 0)
- return self.mounted
-
- def umount(self):
- if self.premounted or not self.mounted:
- return True
- cmd = ['/bin/umount', self.mountpoint]
- self.mounted = not (subprocess.call(cmd) == 0)
- return not self.mounted
-
- def getval(self, item):
- path = os.path.join(self.mountpoint, item)
- f = open(path)
- val = f.readline()
- f.close()
- return val
-
- def putval(self, item, value):
- path = os.path.join(self.mountpoint, item)
- f = open(path, "w")
- f.write(str(value))
- f.close()
-
-class Kmod(object):
- ''' class to manage loading and unloading smi_detector.ko'''
- def __init__(self, module='smi_detector'):
- self.modname = module
- self.preloaded = False
- f = open ('/proc/modules')
- for l in f:
- field = l.split()
- if field[0] == self.modname:
- self.preloaded = True
- break
- f.close
-
- def load(self):
- if self.preloaded:
- return True
- cmd = ['/sbin/modprobe', self.modname]
- return (subprocess.call(cmd) == 0)
-
- def unload(self):
- if self.preloaded:
- return True
- cmd = ['/sbin/modprobe', '-r', self.modname]
- return (subprocess.call(cmd) == 0)
-
-class SMI_Detector(object):
- '''class to wrap access to smi_detector debugfs files'''
- def __init__(self):
- if os.getuid() != 0:
- raise RuntimeError, "Must be root"
- self.debugfs = DebugFS()
- self.kmod = Kmod()
- self.setup()
- self.testduration = 10 # ten seconds
- self.samples = []
-
- def force_cleanup(self):
- debug("forcing unload of smi_detector module")
- self.kmod.preloaded = False
- debug("forcing unmount of debugfs")
- self.debugfs.premounted = False
- self.cleanup()
- debug("exiting")
- sys.exit(0)
-
- def setup(self):
- if not self.debugfs.mount():
- raise RuntimeError, "Failed to mount debugfs"
- if not self.kmod.load():
- raise RuntimeError, "Failed to unload smi_detector"
-
- def cleanup(self):
- if not self.kmod.unload():
- raise RuntimeError, "Failed to unload smi_detector"
- if not self.debugfs.umount():
- raise RuntimeError, "Failed to unmount debugfs"
-
- def get_avg_smi_interval(self):
- return int(self.debugfs.getval("smi_detector/avg_smi_interval"))
-
- def set_agv_smi_interval(self, interval):
- self.debugfs.putval("smi_detector/avg_smi_interval", str(interval))
-
- def get_enable(self):
- return int(self.debugfs.getval("smi_detector/enable"))
-
- def set_enable(self, value):
- self.debugfs.putval("smi_detector/enable", value)
-
- def get_latency_threshold_us(self):
- return int(self.debugfs.getval("smi_detector/latency_threshold_us"))
-
- def set_latency_threshold_us(self, value):
- self.debugfs.putval("smi_detector/latency_threshold_us", value)
-
- def get_max_sample_us(self):
- return int(self.debugfs.getval("smi_detector/max_sample_us"))
-
- def set_max_sample_us(self, value):
- self.debugfs.putval("smi_detector/max_sample_us", value)
-
- def get_ms_between_samples(self):
- return int(self.debugfs.getval("smi_detector/ms_between_samples"))
-
- def set_ms_between_samples(self, value):
- self.debugfs.putval("smi_detector/ms_between_samples", value)
-
- def get_ms_per_sample(self):
- return int(self.debugfs.getval("smi_detector/ms_per_sample"))
-
- def set_ms_per_sample(self, value):
- self.debugfs.putval("smi_detector/ms_per_sample", value)
-
- def get_sample_us(self):
- return int(self.debugfs.getval("smi_detector/sample_us"))
-
- def get_smi_count(self):
- return int(self.debugfs.getval("smi_detector/smi_count"))
-
- def start(self):
- self.set_enable(1)
-
- def stop(self):
- self.set_enable(0)
- while self.get_enable() == 1:
- time.sleep(0.1)
- self.set_enable(0)
-
- def detect(self):
- self.samples = []
- testend = time.time() + self.testduration
- debug("Starting SMI detection for %d seconds" % (self.testduration))
- try:
- self.start()
- while time.time() < testend:
- val = self.get_sample_us()
- self.samples.append(val)
- finally:
- debug("Stopping SMI detection")
- self.stop()
- debug("SMI detection done (%d samples)" % len(self.samples))
-
-def seconds(str):
- "convert input string to value in seconds"
- if str.isdigit():
- return int(str)
- elif str[-2].isalpha():
- raise RuntimeError, "illegal suffix for seconds: '%s'" % str[-2:-1]
- elif str[-1] == 's':
- return int(str[0:-1])
- elif str[-1] == 'm':
- return int(str[0:-1]) * 60
- elif str[-1] == 'h':
- return int(str[0:-1]) * 3600
- elif str[-1] == 'd':
- return int(str[0:-1]) * 86400
- elif str[-1] == 'w':
- return int(str[0:-1]) * 86400 * 7
- else:
- raise RuntimeError, "unknown suffix for seconds: '%s'" % str[-1]
-
-
-def milliseconds(str):
- "convert input string to millsecond value"
-
- if str.isdigit():
- return int(str)
- elif str[-2:] == 'ms':
- return int(str[0:-2])
- elif str[-1] == 's':
- return int(str[0:-2]) * 1000
- elif str[-1] == 'm':
- return int(str[0:-1]) * 1000 * 60
- elif str[-1] == 'h':
- return int(str[0:-1]) * 1000 * 60 * 60
- elif str[-1].isalpha():
- raise RuntimeError, "unknown suffix for milliseconds: '%s'" % str[-1]
- else:
- return int(str)
-
-def microseconds(str):
- "convert input string to microsecond value"
- if str[-2:] == 'ms':
- return int(str[-2] * 1000)
- elif str[-1] == 's':
- return int(str[-1] * 1000 * 1000)
- elif str[-1].isalpha():
- raise RuntimeError, "unknow suffix for microseconds: '%s'" % str[-1]
- else:
- return int(str)
-
-if __name__ == '__main__':
- from optparse import OptionParser
-
- parser = OptionParser()
- parser.add_option("--duration", default=None, type="string",
- dest="duration",
- help="total time to test for SMIs (<n>{smdw})")
-
- parser.add_option("--threshold", default=None, type="string",
- dest="threshold",
- help="value above which is considered an SMI (microseconds")
-
- parser.add_option("--interval", default=None, type="string",
- dest="interval",
- help="time between samples (milliseconds)")
-
- parser.add_option("--sample_width", default=None, type="string",
- dest="sample_width",
- help="time to actually measure (milliseconds)")
-
- parser.add_option("--report", default=None, type="string",
- dest="report",
- help="filename for sample data")
-
- parser.add_option("--cleanup", action="store_true", default=False,
- dest="cleanup",
- help="force unload of module and umount of debugfs")
-
- parser.add_option("--debug", action="store_true", default=False,
- dest="debug",
- help="turn on debugging prints")
-
- parser.add_option("--quiet", action="store_true", default=False,
- dest="quiet",
- help="turn off all screen output")
-
-# parser.add_option("--walk", action="store_true", default=False,
-# dest="walk")
-
- (o, a) = parser.parse_args()
-
- smi = SMI_Detector()
-
- if o.debug:
- debugging = True
-
- if o.quiet:
- quiet = True
-
- if o.cleanup:
- debug("forcing cleanup of debugfs and SMI module")
- smi.force_cleanup()
- sys.exit(0)
-
- if o.threshold:
- t = microseconds(o.threshold)
- smi.set_latency_threshold_us(t)
- debug("threshold set to %dus" % t)
- else:
- smi.set_latency_threshold_us(default_threshold)
- debug("threshold defaulted to %dus" % default_threshold)
-
- if o.interval:
- i = milliseconds(o.interval)
- smi.set_ms_between_samples(i)
- debug("interval between samples set to %dms" % i)
- else:
- smi.set_ms_between_samples(default_interval)
- debug("interval defaulted to %dms" % default_interval)
-
- if o.sample_width:
- w = milliseconds(o.sample_width)
- smi.set_ms_per_sample(w)
- debug("sample width set to %dms" % w)
- else:
- smi.set_ms_per_sample(default_width)
- debug("sample width defaulted to %dms" % default_width)
-
- if o.duration:
- smi.testduration = seconds(o.duration)
- else:
- smi.testduration = 120 # 2 minutes
- debug("test duration is %ds" % smi.testduration)
-
- reportfile = o.report
-
- info("smidetect: test duration %d seconds" % smi.testduration)
- info(" parameters:")
- info(" Latency threshold: %dus" % smi.get_latency_threshold_us())
- info(" Non-sampling gap: %dms" % smi.get_ms_between_samples())
- info(" Sample length: %dms" % smi.get_ms_per_sample())
- info(" Output File: %s" % reportfile)
- info("\nStarting test")
-
- smi.detect()
-
- info("test finished")
-
- exceeding = smi.get_smi_count()
- info("Max Latency: %dus" % smi.get_max_sample_us())
- info("Samples recorded: %d" % len(smi.samples))
- info("Samples exceeding threshold: %d" % exceeding)
-
-
- if reportfile:
- f = open(reportfile, "w")
- for s in smi.samples:
- f.write("%d\n" % s)
- f.close()
- info("sample data written to %s" % reportfile)
- else:
- for s in smi.samples:
- print "%d" % s
-
- smi.cleanup()
- sys.exit(exceeding)