Blame nptl/nptl-printers.py

Packit 6c4009
# Pretty printers for the NPTL lock types.
Packit 6c4009
#
Packit 6c4009
# Copyright (C) 2016-2018 Free Software Foundation, Inc.
Packit 6c4009
# This file is part of the GNU C Library.
Packit 6c4009
#
Packit 6c4009
# The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
# modify it under the terms of the GNU Lesser General Public
Packit 6c4009
# License as published by the Free Software Foundation; either
Packit 6c4009
# version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
#
Packit 6c4009
# The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
# Lesser General Public License for more details.
Packit 6c4009
#
Packit 6c4009
# You should have received a copy of the GNU Lesser General Public
Packit 6c4009
# License along with the GNU C Library; if not, see
Packit 6c4009
# <http://www.gnu.org/licenses/>.
Packit 6c4009
Packit 6c4009
"""This file contains the gdb pretty printers for the following types:
Packit 6c4009
Packit 6c4009
    * pthread_mutex_t
Packit 6c4009
    * pthread_mutexattr_t
Packit 6c4009
    * pthread_cond_t
Packit 6c4009
    * pthread_condattr_t
Packit 6c4009
    * pthread_rwlock_t
Packit 6c4009
    * pthread_rwlockattr_t
Packit 6c4009
Packit 6c4009
You can check which printers are registered and enabled by issuing the
Packit 6c4009
'info pretty-printer' gdb command.  Printers should trigger automatically when
Packit 6c4009
trying to print a variable of one of the types mentioned above.
Packit 6c4009
"""
Packit 6c4009
Packit 6c4009
from __future__ import print_function
Packit 6c4009
Packit 6c4009
import gdb
Packit 6c4009
import gdb.printing
Packit 6c4009
from nptl_lock_constants import *
Packit 6c4009
Packit 6c4009
MUTEX_TYPES = {
Packit 6c4009
    PTHREAD_MUTEX_NORMAL: ('Type', 'Normal'),
Packit 6c4009
    PTHREAD_MUTEX_RECURSIVE: ('Type', 'Recursive'),
Packit 6c4009
    PTHREAD_MUTEX_ERRORCHECK: ('Type', 'Error check'),
Packit 6c4009
    PTHREAD_MUTEX_ADAPTIVE_NP: ('Type', 'Adaptive')
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
class MutexPrinter(object):
Packit 6c4009
    """Pretty printer for pthread_mutex_t."""
Packit 6c4009
Packit 6c4009
    def __init__(self, mutex):
Packit 6c4009
        """Initialize the printer's internal data structures.
Packit 6c4009
Packit 6c4009
        Args:
Packit 6c4009
            mutex: A gdb.value representing a pthread_mutex_t.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        data = mutex['__data']
Packit 6c4009
        self.lock = data['__lock']
Packit 6c4009
        self.count = data['__count']
Packit 6c4009
        self.owner = data['__owner']
Packit 6c4009
        self.kind = data['__kind']
Packit 6c4009
        self.values = []
Packit 6c4009
        self.read_values()
Packit 6c4009
Packit 6c4009
    def to_string(self):
Packit 6c4009
        """gdb API function.
Packit 6c4009
Packit 6c4009
        This is called from gdb when we try to print a pthread_mutex_t.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        return 'pthread_mutex_t'
Packit 6c4009
Packit 6c4009
    def children(self):
Packit 6c4009
        """gdb API function.
Packit 6c4009
Packit 6c4009
        This is called from gdb when we try to print a pthread_mutex_t.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        return self.values
Packit 6c4009
Packit 6c4009
    def read_values(self):
Packit 6c4009
        """Read the mutex's info and store it in self.values.
Packit 6c4009
Packit 6c4009
        The data contained in self.values will be returned by the Iterator
Packit 6c4009
        created in self.children.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        self.read_type()
Packit 6c4009
        self.read_status()
Packit 6c4009
        self.read_attributes()
Packit 6c4009
        self.read_misc_info()
Packit 6c4009
Packit 6c4009
    def read_type(self):
Packit 6c4009
        """Read the mutex's type."""
Packit 6c4009
Packit 6c4009
        mutex_type = self.kind & PTHREAD_MUTEX_KIND_MASK
Packit 6c4009
Packit 6c4009
        # mutex_type must be casted to int because it's a gdb.Value
Packit 6c4009
        self.values.append(MUTEX_TYPES[int(mutex_type)])
Packit 6c4009
Packit 6c4009
    def read_status(self):
Packit 6c4009
        """Read the mutex's status.
Packit 6c4009
Packit 6c4009
        Architectures that support lock elision might not record the mutex owner
Packit 6c4009
        ID in the __owner field.  In that case, the owner will be reported as
Packit 6c4009
        "Unknown".
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        if self.kind == PTHREAD_MUTEX_DESTROYED:
Packit 6c4009
            self.values.append(('Status', 'Destroyed'))
Packit 6c4009
        elif self.kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP:
Packit 6c4009
            self.read_status_robust()
Packit 6c4009
        else:
Packit 6c4009
            self.read_status_no_robust()
Packit 6c4009
Packit 6c4009
    def read_status_robust(self):
Packit 6c4009
        """Read the status of a robust mutex.
Packit 6c4009
Packit 6c4009
        In glibc robust mutexes are implemented in a very different way than
Packit 6c4009
        non-robust ones.  This method reads their locking status,
Packit 6c4009
        whether it may have waiters, their registered owner (if any),
Packit 6c4009
        whether the owner is alive or not, and the status of the state
Packit 6c4009
        they're protecting.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        if self.lock == PTHREAD_MUTEX_UNLOCKED:
Packit 6c4009
            self.values.append(('Status', 'Not acquired'))
Packit 6c4009
        else:
Packit 6c4009
            if self.lock & FUTEX_WAITERS:
Packit 6c4009
                self.values.append(('Status',
Packit 6c4009
                                    'Acquired, possibly with waiters'))
Packit 6c4009
            else:
Packit 6c4009
                self.values.append(('Status',
Packit 6c4009
                                    'Acquired, possibly with no waiters'))
Packit 6c4009
Packit 6c4009
            if self.lock & FUTEX_OWNER_DIED:
Packit 6c4009
                self.values.append(('Owner ID', '%d (dead)' % self.owner))
Packit 6c4009
            else:
Packit 6c4009
                self.values.append(('Owner ID', self.lock & FUTEX_TID_MASK))
Packit 6c4009
Packit 6c4009
        if self.owner == PTHREAD_MUTEX_INCONSISTENT:
Packit 6c4009
            self.values.append(('State protected by this mutex',
Packit 6c4009
                                'Inconsistent'))
Packit 6c4009
        elif self.owner == PTHREAD_MUTEX_NOTRECOVERABLE:
Packit 6c4009
            self.values.append(('State protected by this mutex',
Packit 6c4009
                                'Not recoverable'))
Packit 6c4009
Packit 6c4009
    def read_status_no_robust(self):
Packit 6c4009
        """Read the status of a non-robust mutex.
Packit 6c4009
Packit 6c4009
        Read info on whether the mutex is acquired, if it may have waiters
Packit 6c4009
        and its owner (if any).
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        lock_value = self.lock
Packit 6c4009
Packit 6c4009
        if self.kind & PTHREAD_MUTEX_PRIO_PROTECT_NP:
Packit 6c4009
            lock_value &= ~(PTHREAD_MUTEX_PRIO_CEILING_MASK)
Packit 6c4009
Packit 6c4009
        if lock_value == PTHREAD_MUTEX_UNLOCKED:
Packit 6c4009
            self.values.append(('Status', 'Not acquired'))
Packit 6c4009
        else:
Packit 6c4009
            if self.kind & PTHREAD_MUTEX_PRIO_INHERIT_NP:
Packit 6c4009
                waiters = self.lock & FUTEX_WAITERS
Packit 6c4009
                owner = self.lock & FUTEX_TID_MASK
Packit 6c4009
            else:
Packit 6c4009
                # Mutex protocol is PP or none
Packit 6c4009
                waiters = (self.lock != PTHREAD_MUTEX_LOCKED_NO_WAITERS)
Packit 6c4009
                owner = self.owner
Packit 6c4009
Packit 6c4009
            if waiters:
Packit 6c4009
                self.values.append(('Status',
Packit 6c4009
                                    'Acquired, possibly with waiters'))
Packit 6c4009
            else:
Packit 6c4009
                self.values.append(('Status',
Packit 6c4009
                                    'Acquired, possibly with no waiters'))
Packit 6c4009
Packit 6c4009
            if self.owner != 0:
Packit 6c4009
                self.values.append(('Owner ID', owner))
Packit 6c4009
            else:
Packit 6c4009
                # Owner isn't recorded, probably because lock elision
Packit 6c4009
                # is enabled.
Packit 6c4009
                self.values.append(('Owner ID', 'Unknown'))
Packit 6c4009
Packit 6c4009
    def read_attributes(self):
Packit 6c4009
        """Read the mutex's attributes."""
Packit 6c4009
Packit 6c4009
        if self.kind != PTHREAD_MUTEX_DESTROYED:
Packit 6c4009
            if self.kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP:
Packit 6c4009
                self.values.append(('Robust', 'Yes'))
Packit 6c4009
            else:
Packit 6c4009
                self.values.append(('Robust', 'No'))
Packit 6c4009
Packit 6c4009
            # In glibc, robust mutexes always have their pshared flag set to
Packit 6c4009
            # 'shared' regardless of what the pshared flag of their
Packit 6c4009
            # mutexattr was.  Therefore a robust mutex will act as shared
Packit 6c4009
            # even if it was initialized with a 'private' mutexattr.
Packit 6c4009
            if self.kind & PTHREAD_MUTEX_PSHARED_BIT:
Packit 6c4009
                self.values.append(('Shared', 'Yes'))
Packit 6c4009
            else:
Packit 6c4009
                self.values.append(('Shared', 'No'))
Packit 6c4009
Packit 6c4009
            if self.kind & PTHREAD_MUTEX_PRIO_INHERIT_NP:
Packit 6c4009
                self.values.append(('Protocol', 'Priority inherit'))
Packit 6c4009
            elif self.kind & PTHREAD_MUTEX_PRIO_PROTECT_NP:
Packit 6c4009
                prio_ceiling = ((self.lock & PTHREAD_MUTEX_PRIO_CEILING_MASK)
Packit 6c4009
                                >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT)
Packit 6c4009
Packit 6c4009
                self.values.append(('Protocol', 'Priority protect'))
Packit 6c4009
                self.values.append(('Priority ceiling', prio_ceiling))
Packit 6c4009
            else:
Packit 6c4009
                # PTHREAD_PRIO_NONE
Packit 6c4009
                self.values.append(('Protocol', 'None'))
Packit 6c4009
Packit 6c4009
    def read_misc_info(self):
Packit 6c4009
        """Read miscellaneous info on the mutex.
Packit 6c4009
Packit 6c4009
        For now this reads the number of times a recursive mutex was acquired
Packit 6c4009
        by the same thread.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        mutex_type = self.kind & PTHREAD_MUTEX_KIND_MASK
Packit 6c4009
Packit 6c4009
        if mutex_type == PTHREAD_MUTEX_RECURSIVE and self.count > 1:
Packit 6c4009
            self.values.append(('Times acquired by the owner', self.count))
Packit 6c4009
Packit 6c4009
class MutexAttributesPrinter(object):
Packit 6c4009
    """Pretty printer for pthread_mutexattr_t.
Packit 6c4009
Packit 6c4009
    In the NPTL this is a type that's always casted to struct pthread_mutexattr
Packit 6c4009
    which has a single 'mutexkind' field containing the actual attributes.
Packit 6c4009
    """
Packit 6c4009
Packit 6c4009
    def __init__(self, mutexattr):
Packit 6c4009
        """Initialize the printer's internal data structures.
Packit 6c4009
Packit 6c4009
        Args:
Packit 6c4009
            mutexattr: A gdb.value representing a pthread_mutexattr_t.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        self.values = []
Packit 6c4009
Packit 6c4009
        try:
Packit 6c4009
            mutexattr_struct = gdb.lookup_type('struct pthread_mutexattr')
Packit 6c4009
            self.mutexattr = mutexattr.cast(mutexattr_struct)['mutexkind']
Packit 6c4009
            self.read_values()
Packit 6c4009
        except gdb.error:
Packit 6c4009
            # libpthread doesn't have debug symbols, thus we can't find the
Packit 6c4009
            # real struct type.  Just print the union members.
Packit 6c4009
            self.values.append(('__size', mutexattr['__size']))
Packit 6c4009
            self.values.append(('__align', mutexattr['__align']))
Packit 6c4009
Packit 6c4009
    def to_string(self):
Packit 6c4009
        """gdb API function.
Packit 6c4009
Packit 6c4009
        This is called from gdb when we try to print a pthread_mutexattr_t.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        return 'pthread_mutexattr_t'
Packit 6c4009
Packit 6c4009
    def children(self):
Packit 6c4009
        """gdb API function.
Packit 6c4009
Packit 6c4009
        This is called from gdb when we try to print a pthread_mutexattr_t.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        return self.values
Packit 6c4009
Packit 6c4009
    def read_values(self):
Packit 6c4009
        """Read the mutexattr's info and store it in self.values.
Packit 6c4009
Packit 6c4009
        The data contained in self.values will be returned by the Iterator
Packit 6c4009
        created in self.children.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        mutexattr_type = (self.mutexattr
Packit 6c4009
                          & ~PTHREAD_MUTEXATTR_FLAG_BITS
Packit 6c4009
                          & ~PTHREAD_MUTEX_NO_ELISION_NP)
Packit 6c4009
Packit 6c4009
        # mutexattr_type must be casted to int because it's a gdb.Value
Packit 6c4009
        self.values.append(MUTEX_TYPES[int(mutexattr_type)])
Packit 6c4009
Packit 6c4009
        if self.mutexattr & PTHREAD_MUTEXATTR_FLAG_ROBUST:
Packit 6c4009
            self.values.append(('Robust', 'Yes'))
Packit 6c4009
        else:
Packit 6c4009
            self.values.append(('Robust', 'No'))
Packit 6c4009
Packit 6c4009
        if self.mutexattr & PTHREAD_MUTEXATTR_FLAG_PSHARED:
Packit 6c4009
            self.values.append(('Shared', 'Yes'))
Packit 6c4009
        else:
Packit 6c4009
            self.values.append(('Shared', 'No'))
Packit 6c4009
Packit 6c4009
        protocol = ((self.mutexattr & PTHREAD_MUTEXATTR_PROTOCOL_MASK) >>
Packit 6c4009
                    PTHREAD_MUTEXATTR_PROTOCOL_SHIFT)
Packit 6c4009
Packit 6c4009
        if protocol == PTHREAD_PRIO_NONE:
Packit 6c4009
            self.values.append(('Protocol', 'None'))
Packit 6c4009
        elif protocol == PTHREAD_PRIO_INHERIT:
Packit 6c4009
            self.values.append(('Protocol', 'Priority inherit'))
Packit 6c4009
        elif protocol == PTHREAD_PRIO_PROTECT:
Packit 6c4009
            self.values.append(('Protocol', 'Priority protect'))
Packit 6c4009
Packit 6c4009
class ConditionVariablePrinter(object):
Packit 6c4009
    """Pretty printer for pthread_cond_t."""
Packit 6c4009
Packit 6c4009
    def __init__(self, cond):
Packit 6c4009
        """Initialize the printer's internal data structures.
Packit 6c4009
Packit 6c4009
        Args:
Packit 6c4009
            cond: A gdb.value representing a pthread_cond_t.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        data = cond['__data']
Packit 6c4009
        self.wrefs = data['__wrefs']
Packit 6c4009
        self.values = []
Packit 6c4009
Packit 6c4009
        self.read_values()
Packit 6c4009
Packit 6c4009
    def to_string(self):
Packit 6c4009
        """gdb API function.
Packit 6c4009
Packit 6c4009
        This is called from gdb when we try to print a pthread_cond_t.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        return 'pthread_cond_t'
Packit 6c4009
Packit 6c4009
    def children(self):
Packit 6c4009
        """gdb API function.
Packit 6c4009
Packit 6c4009
        This is called from gdb when we try to print a pthread_cond_t.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        return self.values
Packit 6c4009
Packit 6c4009
    def read_values(self):
Packit 6c4009
        """Read the condvar's info and store it in self.values.
Packit 6c4009
Packit 6c4009
        The data contained in self.values will be returned by the Iterator
Packit 6c4009
        created in self.children.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        self.read_status()
Packit 6c4009
        self.read_attributes()
Packit 6c4009
Packit 6c4009
    def read_status(self):
Packit 6c4009
        """Read the status of the condvar.
Packit 6c4009
Packit 6c4009
        This method reads whether the condvar is destroyed and how many threads
Packit 6c4009
        are waiting for it.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        self.values.append(('Threads known to still execute a wait function',
Packit 6c4009
                            self.wrefs >> PTHREAD_COND_WREFS_SHIFT))
Packit 6c4009
Packit 6c4009
    def read_attributes(self):
Packit 6c4009
        """Read the condvar's attributes."""
Packit 6c4009
Packit 6c4009
        if (self.wrefs & PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0:
Packit 6c4009
            self.values.append(('Clock ID', 'CLOCK_MONOTONIC'))
Packit 6c4009
        else:
Packit 6c4009
            self.values.append(('Clock ID', 'CLOCK_REALTIME'))
Packit 6c4009
Packit 6c4009
        if (self.wrefs & PTHREAD_COND_SHARED_MASK) != 0:
Packit 6c4009
            self.values.append(('Shared', 'Yes'))
Packit 6c4009
        else:
Packit 6c4009
            self.values.append(('Shared', 'No'))
Packit 6c4009
Packit 6c4009
class ConditionVariableAttributesPrinter(object):
Packit 6c4009
    """Pretty printer for pthread_condattr_t.
Packit 6c4009
Packit 6c4009
    In the NPTL this is a type that's always casted to struct pthread_condattr,
Packit 6c4009
    which has a single 'value' field containing the actual attributes.
Packit 6c4009
    """
Packit 6c4009
Packit 6c4009
    def __init__(self, condattr):
Packit 6c4009
        """Initialize the printer's internal data structures.
Packit 6c4009
Packit 6c4009
        Args:
Packit 6c4009
            condattr: A gdb.value representing a pthread_condattr_t.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        self.values = []
Packit 6c4009
Packit 6c4009
        try:
Packit 6c4009
            condattr_struct = gdb.lookup_type('struct pthread_condattr')
Packit 6c4009
            self.condattr = condattr.cast(condattr_struct)['value']
Packit 6c4009
            self.read_values()
Packit 6c4009
        except gdb.error:
Packit 6c4009
            # libpthread doesn't have debug symbols, thus we can't find the
Packit 6c4009
            # real struct type.  Just print the union members.
Packit 6c4009
            self.values.append(('__size', condattr['__size']))
Packit 6c4009
            self.values.append(('__align', condattr['__align']))
Packit 6c4009
Packit 6c4009
    def to_string(self):
Packit 6c4009
        """gdb API function.
Packit 6c4009
Packit 6c4009
        This is called from gdb when we try to print a pthread_condattr_t.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        return 'pthread_condattr_t'
Packit 6c4009
Packit 6c4009
    def children(self):
Packit 6c4009
        """gdb API function.
Packit 6c4009
Packit 6c4009
        This is called from gdb when we try to print a pthread_condattr_t.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        return self.values
Packit 6c4009
Packit 6c4009
    def read_values(self):
Packit 6c4009
        """Read the condattr's info and store it in self.values.
Packit 6c4009
Packit 6c4009
        The data contained in self.values will be returned by the Iterator
Packit 6c4009
        created in self.children.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        clock_id = (self.condattr >> 1) & ((1 << COND_CLOCK_BITS) - 1)
Packit 6c4009
Packit 6c4009
        if clock_id != 0:
Packit 6c4009
            self.values.append(('Clock ID', 'CLOCK_MONOTONIC'))
Packit 6c4009
        else:
Packit 6c4009
            self.values.append(('Clock ID', 'CLOCK_REALTIME'))
Packit 6c4009
Packit 6c4009
        if self.condattr & 1:
Packit 6c4009
            self.values.append(('Shared', 'Yes'))
Packit 6c4009
        else:
Packit 6c4009
            self.values.append(('Shared', 'No'))
Packit 6c4009
Packit 6c4009
class RWLockPrinter(object):
Packit 6c4009
    """Pretty printer for pthread_rwlock_t."""
Packit 6c4009
Packit 6c4009
    def __init__(self, rwlock):
Packit 6c4009
        """Initialize the printer's internal data structures.
Packit 6c4009
Packit 6c4009
        Args:
Packit 6c4009
            rwlock: A gdb.value representing a pthread_rwlock_t.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        data = rwlock['__data']
Packit 6c4009
        self.readers = data['__readers']
Packit 6c4009
        self.cur_writer = data['__cur_writer']
Packit 6c4009
        self.shared = data['__shared']
Packit 6c4009
        self.flags = data['__flags']
Packit 6c4009
        self.values = []
Packit 6c4009
        self.read_values()
Packit 6c4009
Packit 6c4009
    def to_string(self):
Packit 6c4009
        """gdb API function.
Packit 6c4009
Packit 6c4009
        This is called from gdb when we try to print a pthread_rwlock_t.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        return 'pthread_rwlock_t'
Packit 6c4009
Packit 6c4009
    def children(self):
Packit 6c4009
        """gdb API function.
Packit 6c4009
Packit 6c4009
        This is called from gdb when we try to print a pthread_rwlock_t.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        return self.values
Packit 6c4009
Packit 6c4009
    def read_values(self):
Packit 6c4009
        """Read the rwlock's info and store it in self.values.
Packit 6c4009
Packit 6c4009
        The data contained in self.values will be returned by the Iterator
Packit 6c4009
        created in self.children.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        self.read_status()
Packit 6c4009
        self.read_attributes()
Packit 6c4009
Packit 6c4009
    def read_status(self):
Packit 6c4009
        """Read the status of the rwlock."""
Packit 6c4009
Packit 6c4009
        if self.readers & PTHREAD_RWLOCK_WRPHASE:
Packit 6c4009
            if self.readers & PTHREAD_RWLOCK_WRLOCKED:
Packit 6c4009
                self.values.append(('Status', 'Acquired (Write)'))
Packit 6c4009
                self.values.append(('Writer ID', self.cur_writer))
Packit 6c4009
            else:
Packit 6c4009
                self.values.append(('Status', 'Not acquired'))
Packit 6c4009
        else:
Packit 6c4009
            r = self.readers >> PTHREAD_RWLOCK_READER_SHIFT
Packit 6c4009
            if r > 0:
Packit 6c4009
                self.values.append(('Status', 'Acquired (Read)'))
Packit 6c4009
                self.values.append(('Readers', r))
Packit 6c4009
            else:
Packit 6c4009
                self.values.append(('Status', 'Not acquired'))
Packit 6c4009
Packit 6c4009
    def read_attributes(self):
Packit 6c4009
        """Read the attributes of the rwlock."""
Packit 6c4009
Packit 6c4009
        if self.shared:
Packit 6c4009
            self.values.append(('Shared', 'Yes'))
Packit 6c4009
        else:
Packit 6c4009
            self.values.append(('Shared', 'No'))
Packit 6c4009
Packit 6c4009
        if self.flags == PTHREAD_RWLOCK_PREFER_READER_NP:
Packit 6c4009
            self.values.append(('Prefers', 'Readers'))
Packit 6c4009
        elif self.flags == PTHREAD_RWLOCK_PREFER_WRITER_NP:
Packit 6c4009
            self.values.append(('Prefers', 'Writers'))
Packit 6c4009
        else:
Packit 6c4009
            self.values.append(('Prefers', 'Writers no recursive readers'))
Packit 6c4009
Packit 6c4009
class RWLockAttributesPrinter(object):
Packit 6c4009
    """Pretty printer for pthread_rwlockattr_t.
Packit 6c4009
Packit 6c4009
    In the NPTL this is a type that's always casted to
Packit 6c4009
    struct pthread_rwlockattr, which has two fields ('lockkind' and 'pshared')
Packit 6c4009
    containing the actual attributes.
Packit 6c4009
    """
Packit 6c4009
Packit 6c4009
    def __init__(self, rwlockattr):
Packit 6c4009
        """Initialize the printer's internal data structures.
Packit 6c4009
Packit 6c4009
        Args:
Packit 6c4009
            rwlockattr: A gdb.value representing a pthread_rwlockattr_t.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        self.values = []
Packit 6c4009
Packit 6c4009
        try:
Packit 6c4009
            rwlockattr_struct = gdb.lookup_type('struct pthread_rwlockattr')
Packit 6c4009
            self.rwlockattr = rwlockattr.cast(rwlockattr_struct)
Packit 6c4009
            self.read_values()
Packit 6c4009
        except gdb.error:
Packit 6c4009
            # libpthread doesn't have debug symbols, thus we can't find the
Packit 6c4009
            # real struct type.  Just print the union members.
Packit 6c4009
            self.values.append(('__size', rwlockattr['__size']))
Packit 6c4009
            self.values.append(('__align', rwlockattr['__align']))
Packit 6c4009
Packit 6c4009
    def to_string(self):
Packit 6c4009
        """gdb API function.
Packit 6c4009
Packit 6c4009
        This is called from gdb when we try to print a pthread_rwlockattr_t.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        return 'pthread_rwlockattr_t'
Packit 6c4009
Packit 6c4009
    def children(self):
Packit 6c4009
        """gdb API function.
Packit 6c4009
Packit 6c4009
        This is called from gdb when we try to print a pthread_rwlockattr_t.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        return self.values
Packit 6c4009
Packit 6c4009
    def read_values(self):
Packit 6c4009
        """Read the rwlockattr's info and store it in self.values.
Packit 6c4009
Packit 6c4009
        The data contained in self.values will be returned by the Iterator
Packit 6c4009
        created in self.children.
Packit 6c4009
        """
Packit 6c4009
Packit 6c4009
        rwlock_type = self.rwlockattr['lockkind']
Packit 6c4009
        shared = self.rwlockattr['pshared']
Packit 6c4009
Packit 6c4009
        if shared == PTHREAD_PROCESS_SHARED:
Packit 6c4009
            self.values.append(('Shared', 'Yes'))
Packit 6c4009
        else:
Packit 6c4009
            # PTHREAD_PROCESS_PRIVATE
Packit 6c4009
            self.values.append(('Shared', 'No'))
Packit 6c4009
Packit 6c4009
        if rwlock_type == PTHREAD_RWLOCK_PREFER_READER_NP:
Packit 6c4009
            self.values.append(('Prefers', 'Readers'))
Packit 6c4009
        elif rwlock_type == PTHREAD_RWLOCK_PREFER_WRITER_NP:
Packit 6c4009
            self.values.append(('Prefers', 'Writers'))
Packit 6c4009
        else:
Packit 6c4009
            self.values.append(('Prefers', 'Writers no recursive readers'))
Packit 6c4009
Packit 6c4009
def register(objfile):
Packit 6c4009
    """Register the pretty printers within the given objfile."""
Packit 6c4009
Packit 6c4009
    printer = gdb.printing.RegexpCollectionPrettyPrinter('glibc-pthread-locks')
Packit 6c4009
Packit 6c4009
    printer.add_printer('pthread_mutex_t', r'^pthread_mutex_t$',
Packit 6c4009
                        MutexPrinter)
Packit 6c4009
    printer.add_printer('pthread_mutexattr_t', r'^pthread_mutexattr_t$',
Packit 6c4009
                        MutexAttributesPrinter)
Packit 6c4009
    printer.add_printer('pthread_cond_t', r'^pthread_cond_t$',
Packit 6c4009
                        ConditionVariablePrinter)
Packit 6c4009
    printer.add_printer('pthread_condattr_t', r'^pthread_condattr_t$',
Packit 6c4009
                        ConditionVariableAttributesPrinter)
Packit 6c4009
    printer.add_printer('pthread_rwlock_t', r'^pthread_rwlock_t$',
Packit 6c4009
                        RWLockPrinter)
Packit 6c4009
    printer.add_printer('pthread_rwlockattr_t', r'^pthread_rwlockattr_t$',
Packit 6c4009
                        RWLockAttributesPrinter)
Packit 6c4009
Packit 6c4009
    if objfile == None:
Packit 6c4009
        objfile = gdb
Packit 6c4009
Packit 6c4009
    gdb.printing.register_pretty_printer(objfile, printer)
Packit 6c4009
Packit 6c4009
register(gdb.current_objfile())