]> git.saurik.com Git - apple/libpthread.git/blobdiff - tools/locktrace.lua
libpthread-301.50.1.tar.gz
[apple/libpthread.git] / tools / locktrace.lua
diff --git a/tools/locktrace.lua b/tools/locktrace.lua
new file mode 100755 (executable)
index 0000000..ecc64bc
--- /dev/null
@@ -0,0 +1,121 @@
+#!/usr/local/bin/luatrace -s
+
+trace_codename = function(codename, callback)
+       local debugid = trace.debugid(codename)
+       if debugid ~= 0 then
+               trace.single(debugid,callback)
+       else
+               printf("WARNING: Cannot locate debugid for '%s'\n", codename)
+       end
+end
+
+initial_timestamp = 0
+get_prefix = function(buf)
+       if initial_timestamp == 0 then
+               initial_timestamp = buf.timestamp
+       end
+       local secs = trace.convert_timestamp_to_nanoseconds(buf.timestamp - initial_timestamp) / 1000000000
+
+       local prefix
+       if trace.debugid_is_start(buf.debugid) then
+               prefix = "→"
+       elseif trace.debugid_is_end(buf.debugid) then
+               prefix = "←"
+       else
+               prefix = "↔"
+       end
+
+       local proc
+       proc = buf.command
+
+       return string.format("%s %6.9f %-17s [%05d.%06x] %-24s",
+               prefix, secs, proc, buf.pid, buf.threadid, buf.debugname)
+end
+
+decode_lval = function(lval)
+       local kbit = " "
+       if lval & 0x1 ~= 0 then
+               kbit = "K"
+       end
+       local ebit = " "
+       if lval & 0x2 ~= 0 then
+               ebit = "E"
+       end
+       local wbit = " "
+       if lval & 0x4 ~= 0 then
+               wbit = "W"
+       end
+
+       local count = lval >> 8
+       return string.format("[0x%06x, %s%s%s]", count, wbit, ebit, kbit)
+end
+
+decode_sval = function(sval)
+       local sbit = " "
+       if sval & 0x1 ~= 0 then
+               sbit = "S"
+       end
+       local ibit = " "
+       if sval & 0x2 ~= 0 then
+               ibit = "I"
+       end
+
+       local count = sval >> 8
+       return string.format("[0x%06x, %s%s]", count, ibit, sbit)
+end
+
+trace_codename("psynch_mutex_lock_updatebits", function(buf)
+       local prefix = get_prefix(buf)
+       if buf[4] == 0 then
+               printf("%s\tupdated lock bits, pre-kernel (addr: 0x%016x, oldlval: %s, newlval: %s)\n", prefix, buf[1], decode_lval(buf[2]), decode_lval(buf[3]))
+       else
+               printf("%s\tupdated lock bits, post-kernel (addr: 0x%016x, oldlval: %s, newlval: %s)\n", prefix, buf[1], decode_lval(buf[2]), decode_lval(buf[3]))
+       end
+end)
+
+trace_codename("psynch_mutex_unlock_updatebits", function(buf)
+       local prefix = get_prefix(buf)
+       printf("%s\tupdated unlock bits (addr: 0x%016x, oldlval: %s, newlval: %s)\n", prefix, buf[1], decode_lval(buf[2]), decode_lval(buf[3]))
+end)
+
+trace_codename("psynch_mutex_ulock", function(buf)
+       local prefix = get_prefix(buf)
+
+       if trace.debugid_is_start(buf.debugid) then
+               printf("%s\tlock busy, waiting in kernel (addr: 0x%016x, lval: %s, sval: %s, owner_tid: 0x%x)\n",
+                       prefix, buf[1], decode_lval(buf[2]), decode_sval(buf[3]), buf[4])
+       elseif trace.debugid_is_end(buf.debugid) then
+               printf("%s\tlock acquired from kernel (addr: 0x%016x, updated bits: %s)\n",
+                       prefix, buf[1], decode_lval(buf[2]))
+       else
+               printf("%s\tlock taken, uncontended (addr: 0x%016x, lval: %s, sval: %s)\n",
+                       prefix, buf[1], decode_lval(buf[2]), decode_sval(buf[3]))
+       end
+end)
+
+trace_codename("psynch_mutex_utrylock_failed", function(buf)
+       local prefix = get_prefix(buf)
+       printf("%s\tmutex trybusy addr: 0x%016x lval: %s sval: %s owner: 0x%x\n", prefix, buf[1], decode_lval(buf[2]), decode_sval(buf[3]), buf[4])
+end)
+
+trace_codename("psynch_mutex_uunlock", function(buf)
+       local prefix = get_prefix(buf)
+
+       if trace.debugid_is_start(buf.debugid) then
+               printf("%s\tunlock, signalling kernel waiters (addr: 0x%016x, lval: %s, sval: %s, owner_tid: 0x%x)\n",
+                       prefix, buf[1], decode_lval(buf[2]), decode_sval(buf[3]), buf[4])
+       elseif trace.debugid_is_end(buf.debugid) then
+               printf("%s\tunlock, waiters signalled (addr: 0x%016x, updated bits: %s)\n",
+                       prefix, buf[1], decode_lval(buf[2]))
+       else
+               printf("%s\tunlock, no kernel waiters (addr: 0x%016x, lval: %s, sval: %s)\n",
+                       prefix, buf[1], decode_lval(buf[2]), decode_sval(buf[3]))
+       end
+end)
+
+-- The trace codes we need aren't enabled by default
+darwin.sysctlbyname("kern.pthread_debug_tracing", 1)
+completion_handler = function()
+       darwin.sysctlbyname("kern.pthread_debug_tracing", 0)
+end
+trace.set_completion_handler(completion_handler)