This is the mail archive of the archer@sourceware.org mailing list for the Archer project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

"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()


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]