This is the mail archive of the
archer@sourceware.org
mailing list for the Archer project.
"info mutex"
- From: Tom Tromey <tromey at redhat dot com>
- To: Project Archer <archer at sourceware dot org>
- Date: Tue, 13 Jul 2010 11:57:43 -0600
- Subject: "info mutex"
I saw a request for something like this from a user, and so I took a
stab at implementing it yesterday.
This adds a new "info mutex" command that shows the current threads
grouped by mutex. In particular it tries to show what threads are
blocking on a mutex, and what thread owns that mutex.
As is, it only works for pthread mutexes, and you need the glibc
debuginfo installed. Also the output is not as pretty as "info thread":
(gdb) info mutex
Threads not waiting for a lock:
Thread 18453
Mutex 0x8049874:
Owned by thread 18453
* Thread 18456
A couple Python API notes arising from this work:
* It would be nice to have a way to print a thread the way the GDB core
does it. Say, some extended to_string method on gdb.Thread.
* Probably ThreadHolder should be in our library.
* For things like the mutex specifics, it would be nice if libraries
could add their own information when the library-related .py code is
loaded. Maybe we need some generic mechanism for this, since I think
we already also want this for frame filters.
I don't think this code is fully baked enough to check in, but I wanted
to post it in case other people are interested.
Tom
import gdb
class ThreadHolder:
"""A class that can be used with the 'with' statement to save and
restore the current thread while operating on some other thread."""
def __init__(self, thread):
self.thread = thread
def __enter__(self):
self.save = gdb.selected_thread()
self.thread.switch()
def __exit__ (self, exc_type, exc_value, traceback):
try:
self.save.switch()
except:
pass
return None
def print_thread (thr, owner):
"A helper function to nicely print a gdb.Thread."
if thr == selected_thread:
print "* ",
else:
print " ",
if owner:
print "Owned by thread",
else:
print "Thread",
(pid, lwp, tid) = thr.ptid
print "%d " % lwp
# FIXME - function, file name, etc
class InfoMutex(gdb.Command):
def __init__ (self):
gdb.Command.__init__ (self, "info mutex", gdb.COMMAND_NONE)
def invoke (self, arg, from_tty):
# Map a mutex ID to the LWP owning the mutex.
owner = {}
# Map an LWP id to a thread object.
threads = {}
# Map a mutex ID to a list of thread objects that are waiting
# for the lock.
mutexes = {}
for inf in gdb.inferiors():
for thr in inf.threads():
id = thr.ptid[1]
threads[id] = thr
with ThreadHolder (thr):
frame = gdb.selected_frame()
lock_name = None
for n in range(5):
if frame is None:
break
fn_sym = frame.function()
if fn_sym is not None and (fn_sym.name == '__pthread_mutex_lock' or fn_sym.name == '__pthread_mutex_lock_full' or fn_sym.name == 'pthread_mutex_timedlock'):
m = frame.read_var ('mutex')
lock_name = long (m)
if lock_name not in owner:
owner[lock_name] = long (m['__data']['__owner'])
break
frame = frame.older()
if lock_name not in mutexes:
mutexes[lock_name] = []
mutexes[lock_name] += [thr]
selected_thread = gdb.selected_thread()
for id in mutexes.keys():
if id is None:
print "Threads not waiting for a lock:"
else:
print "Mutex 0x%x:" % id
print_thread (threads[owner[id]], True)
for thr in mutexes[id]:
print_thread (thr, False)
print
InfoMutex()