diff options
author | Clark Williams <williams@redhat.com> | 2009-06-12 13:20:17 -0500 |
---|---|---|
committer | Clark Williams <williams@redhat.com> | 2009-06-12 13:20:17 -0500 |
commit | 3e04327f7fc0be0ee2cb3d8157a4faf43e4b00cb (patch) | |
tree | 2c71e3a9a975ce1f829a6244b4284e01cea014e5 | |
parent | c7deee8c38a08e173a5e5282280c2abb362c9370 (diff) | |
parent | 11f68bd172b13866666837fc9534c0f7b5eb338e (diff) | |
download | rt-tests-3e04327f7fc0be0ee2cb3d8157a4faf43e4b00cb.tar.gz rt-tests-3e04327f7fc0be0ee2cb3d8157a4faf43e4b00cb.tar.xz |
merge resolutionv0.41
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Makefile | 15 | ||||
-rw-r--r-- | rt-tests.spec-in | 4 | ||||
-rw-r--r-- | src/cyclictest/cyclictest.c | 12 | ||||
-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-x | src/hwlatdetect/hwlatdetect.py | 356 | ||||
-rw-r--r-- | src/smidetect/smidetect.py | 352 |
8 files changed, 392 insertions, 381 deletions
@@ -13,3 +13,5 @@ classic_pi pi_stress cyclictest signaltest +rt-tests.spec +smidetect @@ -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) |