Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
examples/systemtap/lock-debug.stp | 115 ++++++++++++++++++++++++++++++++++++++
1 file changed, 115 insertions(+)
create mode 100644 examples/systemtap/lock-debug.stp
diff --git a/examples/systemtap/lock-debug.stp b/examples/systemtap/lock-debug.stp
new file mode 100644
index 0000000..bf18bc6
--- /dev/null
+++ b/examples/systemtap/lock-debug.stp
@@ -0,0 +1,115 @@
+#!/usr/bin/stap --ldd -d /usr/sbin/libvirtd -c libvirtd
+#
+# Usage with installed libvirt daemon:
+# stap --ldd -d /usr/sbin/libvirtd -c libvirtd \
+# lock-debug.stp /usr/lib/libvirt.so
+#
+# If made executable; simple './lock-debug.stp' should work too.
+#
+# TODO: Document usage with uninstalled daemon and libs.
+# Assuming CWD is toplevel source git directory, it should be only
+# slight modification to the following:
+#
+# ./run stap --ldd -c daemon/libvirtd -d daemon/libvirtd
+# examples/systemtap/lock-debug.stp src/.libs/libvirt.so
+#
+# Author: Martin Kletzander <mkletzan(a)redhat.com>
+
+global mx_tolock
+global mx_locked
+
+
+function filter()
+{
+ if (pid() != target())
+ return 1
+
+ return 0
+}
+
+probe library = process( %( $# > 0 %? @1 %: "/usr/lib/libvirt.so" %) )
+{
+ if (filter()) next
+}
+
+probe lock = library.function("virMutexLock")
+{
+ lockname = usymdata($m)
+}
+
+probe unlock = library.function("virMutexUnlock")
+{
+ lockname = usymdata($m)
+}
+
+probe begin
+{
+ %( $# > 1 %? println("error: Too many parameters"); exit();
+ %: print("Started, press ^C when the proccess hangs\n"); %)
+}
+
+probe lock.call
+{
+ mx_tolock[lockname, tid()] = sprint_ubacktrace()
+}
+
+probe lock.return
+{
+ if ([lockname, tid()] in mx_tolock) {
+ mx_locked[lockname, tid()] = mx_tolock[lockname, tid()]
+ delete mx_tolock[lockname, tid()]
+ } else {
+ printf("internal error: lock acquired unwillingly?\n")
+ }
+}
+
+probe unlock.return
+{
+ found = 0
+
+ foreach ([lock, tid] in mx_locked) {
+ if (lock != lockname)
+ continue
+ if (tid != tid()) {
+ printf("Warning: lock released on different thread that locked
it.\n");
+ printf("Lock trace:\n%s\n", mx_locked[lock, tid])
+ printf("Unlock trace:\n%s\n", sprint_ubacktrace())
+ }
+
+ found = tid
+ break
+ }
+
+ if (found) {
+ if ([lockname, found] in mx_locked)
+ delete mx_locked[lockname, found]
+ else
+ println("FDSA")
+ } else {
+ printf("Warning: lock released without being locked.\n")
+ printf("Unlock trace:\n%s\n", sprint_ubacktrace())
+ }
+}
+
+probe end
+{
+ printf("\n=============\n")
+
+ tmp = 0;
+ foreach (bt = [lock, tid] in mx_locked) {
+ if (!tmp++)
+ printf("The following locks are locked:\n")
+ printf("%s(%d):\n%s\n---\n", lock, tid, bt)
+ }
+ if (!tmp)
+ printf("No locks are locked, apparently\n")
+
+ tmp = 0;
+ foreach (bt = [lock, tid] in mx_tolock) {
+ if (!tmp++)
+ printf("The following locks are waiting to be acquired:\n")
+ printf("%s(%d):\n%s\n---\n", lock, tid, bt)
+ }
+ if (!tmp)
+ printf("No locks are being acquired, apparently\n")
+}
--
2.1.0