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