diff options
author | Siddhesh Poyarekar <siddhesh@sourceware.org> | 2016-07-11 20:32:12 +0530 |
---|---|---|
committer | Siddhesh Poyarekar <siddhesh@sourceware.org> | 2016-07-11 20:32:12 +0530 |
commit | c10f90dcef42092a96007fed7e77f9d470e5bb76 (patch) | |
tree | d4e260bbfec4a61d50a17f3be8fc64a0b7b01b4b | |
parent | 26c2910ac6889dd21f128d9071418492d544a2dc (diff) | |
download | glibc-c10f90dcef42092a96007fed7e77f9d470e5bb76.zip glibc-c10f90dcef42092a96007fed7e77f9d470e5bb76.tar.gz glibc-c10f90dcef42092a96007fed7e77f9d470e5bb76.tar.bz2 |
Revert "Add pretty printers for the NPTL lock types"
This reverts commit 62ce266b0b261def2c6329be9814ffdcc11964d6.
The change is not mature enough because it needs the following fixes:
1. Redirect test output to a file like other tests
2. Eliminate the need to use a .gdbinit because distributions will
break without it. I should have caught that but I was in too much
of a hurry to get the patch in :/
3. Feature checking during configure to determine things like minimum
required gdb version, python-pexpect version, etc. to make sure
that tests work correctly.
-rw-r--r-- | ChangeLog | 27 | ||||
-rw-r--r-- | Makeconfig | 14 | ||||
-rw-r--r-- | Makerules | 46 | ||||
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | Rules | 5 | ||||
-rw-r--r-- | nptl/Makefile | 1 | ||||
-rw-r--r-- | nptl/nptl-printers.py | 593 | ||||
-rw-r--r-- | nptl/nptl_lock_constants.pysym | 75 | ||||
-rw-r--r-- | pretty-printers/Makefile | 82 | ||||
-rw-r--r-- | pretty-printers/README | 130 | ||||
-rw-r--r-- | pretty-printers/test-condvar-attributes.c | 94 | ||||
-rw-r--r-- | pretty-printers/test-condvar-attributes.py | 60 | ||||
-rw-r--r-- | pretty-printers/test-condvar-printer.c | 57 | ||||
-rw-r--r-- | pretty-printers/test-condvar-printer.py | 45 | ||||
-rw-r--r-- | pretty-printers/test-mutex-attributes.c | 144 | ||||
-rw-r--r-- | pretty-printers/test-mutex-attributes.py | 90 | ||||
-rw-r--r-- | pretty-printers/test-mutex-printer.c | 151 | ||||
-rw-r--r-- | pretty-printers/test-mutex-printer.py | 92 | ||||
-rw-r--r-- | pretty-printers/test-rwlock-attributes.c | 98 | ||||
-rw-r--r-- | pretty-printers/test-rwlock-attributes.py | 62 | ||||
-rw-r--r-- | pretty-printers/test-rwlock-printer.c | 78 | ||||
-rw-r--r-- | pretty-printers/test-rwlock-printer.py | 59 | ||||
-rw-r--r-- | pretty-printers/test_common.py | 315 | ||||
-rw-r--r-- | scripts/gen-py-const.awk | 118 |
24 files changed, 1 insertions, 2438 deletions
@@ -34,33 +34,6 @@ * sysdeps/unix/sysv/linux/pwritev64.c [__WORDSIZE != 64 || __ASSUME_OFF_DIFF_OFF64] (pwritev64): Likewise. -2016-07-08 Martin Galvan <martin.galvan@tallertechnologies.com> - - * Makeconfig (build-hardcoded-path-in-tests): Set to 'yes' - for shared builds if tests-need-hardcoded-path is defined. - (all-subdirs): Add pretty-printers. - * Makerules ($(py-const)): New rule. - * Rules (others): Add $(py-const), if defined. - * nptl/Makefile (gen-py-const-headers): Define. - * nptl/nptl-printers.py: New file. - * nptl/nptl_lock_constants.pysym: Likewise. - * pretty-printers/Makefile: Likewise. - * pretty-printers/README: Likewise. - * pretty-printers/test-condvar-attributes.c: Likewise. - * pretty-printers/test-condvar-attributes.p: Likewise. - * pretty-printers/test-condvar-printer.c: Likewise. - * pretty-printers/test-condvar-printer.py: Likewise. - * pretty-printers/test-mutex-attributes.c: Likewise. - * pretty-printers/test-mutex-attributes.py: Likewise. - * pretty-printers/test-mutex-printer.c: Likewise. - * pretty-printers/test-mutex-printer.py: Likewise. - * pretty-printers/test-rwlock-attributes.c: Likewise. - * pretty-printers/test-rwlock-attributes.py: Likewise. - * pretty-printers/test-rwlock-printer.c: Likewise. - * pretty-printers/test-rwlock-printer.py: Likewise. - * pretty-printers/test_common.py: Likewise. - * scripts/gen-py-const.awk: Likewise. - 2016-07-08 Chris Metcalf <cmetcalf@mellanox.com> * sysdeps/unix/sysv/linux/tile/kernel-features.h @@ -472,18 +472,6 @@ else +link-tests = $(+link-static-tests) endif endif - -# Some modules may have test programs that must always link against the newly -# built libraries instead of the installed ones. Such modules must define -# tests-need-hardcoded-path in their Makefile before including Makerules. -# This will cause the test programs to be linked with -rpath instead of -# -rpath-link, and their dynamic linker will be set to the built ld.so. -ifeq (yes,$(build-shared)) -ifdef tests-need-hardcoded-path -build-hardcoded-path-in-tests := yes -endif -endif - ifeq (yes,$(build-shared)) ifndef rtld-LDFLAGS rtld-LDFLAGS = -Wl,-dynamic-linker=$(rtlddir)/$(rtld-installed-name) @@ -1109,7 +1097,7 @@ all-subdirs = csu assert ctype locale intl catgets math setjmp signal \ grp pwd posix io termios resource misc socket sysvipc gmon \ gnulib iconv iconvdata wctype manual shadow gshadow po argp \ crypt localedata timezone rt conform debug mathvec \ - $(add-on-subdirs) dlfcn elf pretty-printers + $(add-on-subdirs) dlfcn elf ifndef avoid-generated # sysd-sorted itself will contain rules making the sysd-sorted target @@ -214,52 +214,6 @@ sed-remove-dotdot := -e 's@ *\([^ \/$$][^ \]*\)@ $$(..)\1@g' \ -e 's@^\([^ \/$$][^ \]*\)@$$(..)\1@g' endif -ifdef gen-py-const-headers -# We'll use a static pattern rule to match .pysym files with their -# corresponding generated .py files. -# The generated .py files go in the submodule's dir in the glibc source dir. -py-const-files := $(patsubst %.pysym,%.py,$(gen-py-const-headers)) -py-const-dir := $(objpfx) -py-const := $(addprefix $(py-const-dir),$(py-const-files)) -py-const-script := $(..)scripts/gen-py-const.awk - -# This is a hack we use to generate .py files with constants for Python -# pretty printers. It works the same way as gen-as-const. -# See scripts/gen-py-const.awk for details on how the awk | gcc mechanism -# works. -# -# $@.tmp and $@.tmp2 are temporary files we use to store the partial contents -# of the target file. We do this instead of just writing on $@ because, if the -# build process terminates prematurely, re-running Make wouldn't run this rule -# since Make would see that the target file already exists (despite it being -# incomplete). -# -# The sed line replaces "@name@SOME_NAME@value@SOME_VALUE@" strings from the -# output of 'gcc -S' with "SOME_NAME = SOME_VALUE" strings. -# The '-n' option, combined with the '/p' command, makes sed output only the -# modified lines instead of the whole input file. The output is redirected -# to a .py file; we'll import it in the pretty printers file to read -# the constants generated by gen-py-const.awk. -# The regex has two capturing groups, for SOME_NAME and SOME_VALUE -# respectively. Notice SOME_VALUE may be prepended by a special character, -# depending on the assembly syntax (e.g. immediates are prefixed by a '$' -# in AT&T x86, and by a '#' in ARM). We discard it using a complemented set -# before the second capturing group. -$(py-const): $(py-const-dir)%.py: %.pysym $(py-const-script) \ - $(common-before-compile) - $(make-target-directory) - $(AWK) -f $(py-const-script) $< \ - | $(CC) -S -o $@.tmp $(CFLAGS) $(CPPFLAGS) -x c - - echo '# GENERATED FILE\n' > $@.tmp2 - echo '# Constant definitions for pretty printers.' >> $@.tmp2 - echo '# See gen-py-const.awk for details.\n' >> $@.tmp2 - sed -n -r 's/^.*@name@([^@]+)@value@[^[:xdigit:]Xx-]*([[:xdigit:]Xx-]+)@.*/\1 = \2/p' \ - $@.tmp >> $@.tmp2 - mv -f $@.tmp2 $@ - rm -f $@.tmp - -generated += $(py-const) -endif # gen-py-const-headers ifdef gen-as-const-headers # Generating headers for assembly constants. @@ -47,9 +47,6 @@ Version 2.24 direction of negative infinity. These are currently enabled as GNU extensions. -* Initial support is added for pretty printing of pthread variables in gdb. - See pretty-printers/README for details on how to use it. - Security related changes: * An unnecessary stack copy in _nss_dns_getnetbyname_r was removed. It @@ -98,11 +98,6 @@ tests: $(tests:%=$(objpfx)%.out) $(tests-special) xtests: tests $(xtests:%=$(objpfx)%.out) $(xtests-special) endif -# Generate constant files for Python pretty printers if required. -ifdef py-const -others: $(py-const) -endif - tests-special-notdir = $(patsubst $(objpfx)%, %, $(tests-special)) xtests-special-notdir = $(patsubst $(objpfx)%, %, $(xtests-special)) tests: diff --git a/nptl/Makefile b/nptl/Makefile index 09e09dd..0d8aade 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -307,7 +307,6 @@ gen-as-const-headers = pthread-errnos.sym \ unwindbuf.sym \ lowlevelrobustlock.sym pthread-pi-defines.sym -gen-py-const-headers = nptl_lock_constants.pysym LDFLAGS-pthread.so = -Wl,--enable-new-dtags,-z,nodelete,-z,initfirst diff --git a/nptl/nptl-printers.py b/nptl/nptl-printers.py deleted file mode 100644 index f64216f..0000000 --- a/nptl/nptl-printers.py +++ /dev/null @@ -1,593 +0,0 @@ -# Pretty printers for the NPTL lock types. -# -# Copyright (C) 2016 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 -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. - - For architectures which support lock elision, this method reads - whether the mutex appears as locked in memory (i.e. it may show it as - unlocked even after calling pthread_mutex_lock). - """ - - 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', 'Unlocked')) - else: - if self.lock & FUTEX_WAITERS: - self.values.append(('Status', 'Locked, possibly with waiters')) - else: - self.values.append(('Status', - 'Locked, 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 locked, 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', 'Unlocked')) - 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', 'Locked, possibly with waiters')) - else: - self.values.append(('Status', - 'Locked, possibly with no waiters')) - - self.values.append(('Owner ID', owner)) - - 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 locked - 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 locked recursively', 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. - """ - - mutexattr_struct = gdb.lookup_type('struct pthread_mutexattr') - self.mutexattr = mutexattr.cast(mutexattr_struct)['mutexkind'] - self.values = [] - self.read_values() - - 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')) - -CLOCK_IDS = { - CLOCK_REALTIME: 'CLOCK_REALTIME', - CLOCK_MONOTONIC: 'CLOCK_MONOTONIC', - CLOCK_PROCESS_CPUTIME_ID: 'CLOCK_PROCESS_CPUTIME_ID', - CLOCK_THREAD_CPUTIME_ID: 'CLOCK_THREAD_CPUTIME_ID', - CLOCK_MONOTONIC_RAW: 'CLOCK_MONOTONIC_RAW', - CLOCK_REALTIME_COARSE: 'CLOCK_REALTIME_COARSE', - CLOCK_MONOTONIC_COARSE: 'CLOCK_MONOTONIC_COARSE' -} - -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.total_seq = data['__total_seq'] - self.mutex = data['__mutex'] - self.nwaiters = data['__nwaiters'] - 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() - self.read_mutex_info() - - 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. - """ - - if self.total_seq == PTHREAD_COND_DESTROYED: - self.values.append(('Status', 'Destroyed')) - - self.values.append(('Threads waiting for this condvar', - self.nwaiters >> COND_NWAITERS_SHIFT)) - - def read_attributes(self): - """Read the condvar's attributes.""" - - clock_id = self.nwaiters & ((1 << COND_NWAITERS_SHIFT) - 1) - - # clock_id must be casted to int because it's a gdb.Value - self.values.append(('Clock ID', CLOCK_IDS[int(clock_id)])) - - shared = (self.mutex == PTHREAD_COND_SHARED) - - if shared: - self.values.append(('Shared', 'Yes')) - else: - self.values.append(('Shared', 'No')) - - def read_mutex_info(self): - """Read the data of the mutex this condvar is bound to. - - A pthread_cond_t's __data.__mutex member is a void * which - must be casted to pthread_mutex_t *. For shared condvars, this - member isn't recorded and has a value of ~0l instead. - """ - - if self.mutex and self.mutex != PTHREAD_COND_SHARED: - mutex_type = gdb.lookup_type('pthread_mutex_t') - mutex = self.mutex.cast(mutex_type.pointer()).dereference() - - self.values.append(('Mutex', mutex)) - -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. - """ - - condattr_struct = gdb.lookup_type('struct pthread_condattr') - self.condattr = condattr.cast(condattr_struct)['value'] - self.values = [] - self.read_values() - - 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 << COND_NWAITERS_SHIFT) - 1) - - # clock_id must be casted to int because it's a gdb.Value - self.values.append(('Clock ID', CLOCK_IDS[int(clock_id)])) - - 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['__nr_readers'] - self.queued_readers = data['__nr_readers_queued'] - self.queued_writers = data['__nr_writers_queued'] - self.writer_id = data['__writer'] - self.shared = data['__shared'] - self.prefers_writers = 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.""" - - # Right now pthread_rwlock_destroy doesn't do anything, so there's no - # way to check if an rwlock is destroyed. - - if self.writer_id: - self.values.append(('Status', 'Locked (Write)')) - self.values.append(('Writer ID', self.writer_id)) - elif self.readers: - self.values.append(('Status', 'Locked (Read)')) - self.values.append(('Readers', self.readers)) - else: - self.values.append(('Status', 'Unlocked')) - - self.values.append(('Queued readers', self.queued_readers)) - self.values.append(('Queued writers', self.queued_writers)) - - 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.prefers_writers: - self.values.append(('Prefers', 'Writers')) - else: - self.values.append(('Prefers', '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. - """ - - rwlockattr_struct = gdb.lookup_type('struct pthread_rwlockattr') - self.rwlockattr = rwlockattr.cast(rwlockattr_struct) - self.values = [] - self.read_values() - - 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 or - rwlock_type == PTHREAD_RWLOCK_PREFER_WRITER_NP): - # This is a known bug. Using PTHREAD_RWLOCK_PREFER_WRITER_NP will - # still make the rwlock prefer readers. - self.values.append(('Prefers', 'Readers')) - elif rwlock_type == PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP: - self.values.append(('Prefers', 'Writers')) - -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) - - gdb.printing.register_pretty_printer(objfile, printer) - -register(gdb.current_objfile()) diff --git a/nptl/nptl_lock_constants.pysym b/nptl/nptl_lock_constants.pysym deleted file mode 100644 index e6ac427..0000000 --- a/nptl/nptl_lock_constants.pysym +++ /dev/null @@ -1,75 +0,0 @@ -#include <pthreadP.h> - --- Mutex types -PTHREAD_MUTEX_KIND_MASK PTHREAD_MUTEX_KIND_MASK_NP -PTHREAD_MUTEX_NORMAL -PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP -PTHREAD_MUTEX_ERRORCHECK PTHREAD_MUTEX_ERRORCHECK_NP -PTHREAD_MUTEX_ADAPTIVE_NP - --- Mutex status --- These are hardcoded all over the code; there are no enums/macros for them. -PTHREAD_MUTEX_DESTROYED -1 -PTHREAD_MUTEX_UNLOCKED 0 -PTHREAD_MUTEX_LOCKED_NO_WAITERS 1 - --- For robust mutexes -PTHREAD_MUTEX_INCONSISTENT -PTHREAD_MUTEX_NOTRECOVERABLE -FUTEX_OWNER_DIED - --- For robust and PI mutexes -FUTEX_WAITERS -FUTEX_TID_MASK - --- Mutex attributes -PTHREAD_MUTEX_ROBUST_NORMAL_NP -PTHREAD_MUTEX_PRIO_INHERIT_NP -PTHREAD_MUTEX_PRIO_PROTECT_NP -PTHREAD_MUTEX_PSHARED_BIT -PTHREAD_MUTEX_PRIO_CEILING_SHIFT -PTHREAD_MUTEX_PRIO_CEILING_MASK - --- Mutex attribute flags -PTHREAD_MUTEXATTR_PROTOCOL_SHIFT -PTHREAD_MUTEXATTR_PROTOCOL_MASK -PTHREAD_MUTEXATTR_PRIO_CEILING_MASK -PTHREAD_MUTEXATTR_FLAG_ROBUST -PTHREAD_MUTEXATTR_FLAG_PSHARED -PTHREAD_MUTEXATTR_FLAG_BITS -PTHREAD_MUTEX_NO_ELISION_NP - --- Priority protocols -PTHREAD_PRIO_NONE -PTHREAD_PRIO_INHERIT -PTHREAD_PRIO_PROTECT - --- These values are hardcoded as well: --- Value of __mutex for shared condvars. -PTHREAD_COND_SHARED ~0l - --- Value of __total_seq for destroyed condvars. -PTHREAD_COND_DESTROYED -1ull - --- __nwaiters encodes the number of threads waiting on a condvar --- and the clock ID. --- __nwaiters >> COND_NWAITERS_SHIFT gives us the number of waiters. -COND_NWAITERS_SHIFT - --- Condvar clock IDs -CLOCK_REALTIME -CLOCK_MONOTONIC -CLOCK_PROCESS_CPUTIME_ID -CLOCK_THREAD_CPUTIME_ID -CLOCK_MONOTONIC_RAW -CLOCK_REALTIME_COARSE -CLOCK_MONOTONIC_COARSE - --- Rwlock attributes -PTHREAD_RWLOCK_PREFER_READER_NP -PTHREAD_RWLOCK_PREFER_WRITER_NP -PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP - --- 'Shared' attribute values -PTHREAD_PROCESS_PRIVATE -PTHREAD_PROCESS_SHARED diff --git a/pretty-printers/Makefile b/pretty-printers/Makefile deleted file mode 100644 index 8423897..0000000 --- a/pretty-printers/Makefile +++ /dev/null @@ -1,82 +0,0 @@ -# Makefile for the Python pretty printers. -# -# Copyright (C) 2016 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 contains rules for building and running the pretty printer tests. - -subdir := pretty-printers -tests-need-hardcoded-path := yes - -include ../Makeconfig - -PYTHON := python - -tests-pretty-printers := test-mutex-attributes test-mutex-printer \ - test-condvar-attributes test-condvar-printer \ - test-rwlock-attributes test-rwlock-printer - -# Add the test programs to test-srcs so that they'll be compiled regardless -# of whether we should actually run them. -test-srcs := $(tests-pretty-printers) - -ifeq ($(build-shared),yes) -nptl-tests-libs := $(shared-thread-library) -else -nptl-tests-libs := $(static-thread-library) -endif - -# The test programs need to be compiled without optimizations so they won't -# confuse gdb. We could use either the 'GCC optimize' pragma or the 'optimize' -# function attribute to achieve this; however, at least on ARM, gcc always -# produces different debugging symbols when invoked with a -O greater than 0 -# than when invoked with -O0, regardless of anything else we're using -# to suppress optimizations. Therefore, we need to explicitly pass -O0 to it -# through CFLAGS. -# Additionally, the build system will try to -include $(common-objpfx)/config.h -# when compiling the tests, which will throw an error if some special macros -# (such as __OPTIMIZE__ and IS_IN_BUILD) aren't defined. To avoid this, we -# tell gcc to define IS_IN_build. -CFLAGS-test-mutex-attributes.c := -O0 -ggdb3 -DIS_IN_build -CFLAGS-test-mutex-printer.c := -O0 -ggdb3 -DIS_IN_build -CFLAGS-test-condvar-attributes.c := -O0 -ggdb3 -DIS_IN_build -CFLAGS-test-condvar-printer.c := -O0 -ggdb3 -DIS_IN_build -CFLAGS-test-rwlock-attributes.c := -O0 -ggdb3 -DIS_IN_build -CFLAGS-test-rwlock-printer.c := -O0 -ggdb3 -DIS_IN_build - -tests-pretty-printers-dest := $(addprefix $(objpfx),$(tests-pretty-printers)) -tests-pretty-printers-pp := $(addsuffix -pp,$(tests-pretty-printers-dest)) - -ifeq ($(run-built-tests),yes) -tests-special += $(tests-pretty-printers-pp) -endif - -include ../Rules - -# Add the thread libraries to the prerequisites of the NPTL test programs. -$(tests-pretty-printers-dest): $(nptl-tests-libs) - -# We won't actually create any *-pp files, so we mark this target as PHONY -# to ensure it always runs when required. -.PHONY: $(tests-pretty-printers-pp) - -# Static pattern rule that matches the test-* targets to their .c and .py -# prerequisites. It'll run the corresponding test script for each test program -# we compiled. test_common.py must be present for all. -$(tests-pretty-printers-pp): $(objpfx)%-pp: $(objpfx)% %.py test_common.py - $(test-wrapper-env) $(PYTHON) $*.py $*.c $(objpfx)$*; \ - $(evaluate-test) diff --git a/pretty-printers/README b/pretty-printers/README deleted file mode 100644 index ff35d7e..0000000 --- a/pretty-printers/README +++ /dev/null @@ -1,130 +0,0 @@ -README for the glibc Python pretty printers -------------------------------------------- - -Pretty printers are gdb extensions that allow it to print useful, human-readable -information about a program's variables. For example, for a pthread_mutex_t -gdb would usually output something like this: - -(gdb) print mutex -$1 = { - __data = { - __lock = 22020096, - __count = 0, - __owner = 0, - __nusers = 0, - __kind = 576, - __spins = 0, - __elision = 0, - __list = { - __prev = 0x0, - __next = 0x0 - } - }, - __size = "\000\000P\001", '\000' <repeats 12 times>, "@\002", '\000' <repeats 21 times>, - __align = 22020096 -} - -However, with a pretty printer gdb will output something like this: - -(gdb) print mutex -$1 = pthread_mutex_t = { - Type = Normal, - Status = Unlocked, - Robust = No, - Shared = No, - Protocol = Priority protect, - Priority ceiling = 42 -} - -Before printing a value, gdb will first check if there's a pretty printer -registered for it. If there is, it'll use it, otherwise it'll print the value -as usual. Pretty printers can be registered in various ways; for our purposes -we register them for the current objfile by calling -gdb.printing.register_pretty_printer(). - -Currently our printers are based on gdb.RegexpCollectionPrettyPrinter, which -means they'll be triggered if the type of the variable we're printing matches -a given regular expression. For example, MutexPrinter will be triggered if -our variable's type matches the regexp '^pthread_mutex_t$'. - -Besides the printers themselves, each module may have a constants file which the -printers will import. These constants are generated from C headers during the -build process, and need to be in the Python search path when loading the -printers. - - -Installing and loading ----------------------- - -The pretty printers and their constant files may be installed in different paths -for each distro, though gdb should be able to automatically load them by itself. -When in doubt, you can use the 'info pretty printer' gdb command to list the -loaded pretty printers. - -If the printers aren't automatically loaded for some reason, you should add the -following to your .gdbinit: - -python -import sys -sys.path.insert(0, '/path/to/constants/file/directory') -end - -source /path/to/printers.py - -If you're building glibc manually, '/path/to/constants/file/directory' should be -'/path/to/glibc-build/submodule', where 'submodule' is e.g. nptl. - - -Testing -------- - -The pretty printers come with a small test suite based on PExpect, which is a -Python module with Expect-like features for spawning and controlling interactive -programs. Each printer has a corresponding C program and a Python script -that uses PExpect to drive gdb through the program and compare its output to -the expected printer's. - -The tests run on the glibc host, which is assumed to have both gdb and PExpect; -if any of those is absent the tests will fail with code 77 (UNSUPPORTED). -Native builds can be tested simply by doing 'make check'; cross builds must use -cross-test-ssh.sh as test-wrapper, like this: - -make test-wrapper='/path/to/scripts/cross-test-ssh.sh user@host' check - -(Remember to share the build system's filesystem with the glibc host's through -NFS or something similar). - -Running 'make check' on a cross build will only compile the test programs, -without running the scripts. - - -Known issues ------------- - -* Pretty printers are inherently coupled to the code they're targetting, thus -any changes to the target code must also update the corresponding printers. -On the plus side, the printer code itself may serve as a kind of documentation -for the target code. - -* Older versions of the gdb Python API have a bug where -gdb.RegexpCollectionPrettyPrinter would not be able to get a value's real type -if it was typedef'd. This would cause gdb to ignore the pretty printers for -types like pthread_mutex_t, which is defined as: - -typedef union -{ - ... -} pthread_mutex_t; - -This was fixed in commit 1b588015839caafc608a6944a78aea170f5fb2f6. However, -typedef'ing an already typedef'd type may cause a similar issue, e.g.: - -typedef pthread_mutex_t mutex; -mutex a_mutex; - -Here, trying to print a_mutex won't trigger the pthread_mutex_t printer. - -* The test programs must be compiled without optimizations. This is necessary -because the test scripts rely on the C code structure being preserved when -stepping through the programs. Things like aggressive instruction reordering -or optimizing variables out may make this kind of testing impossible. diff --git a/pretty-printers/test-condvar-attributes.c b/pretty-printers/test-condvar-attributes.c deleted file mode 100644 index 4db4098..0000000 --- a/pretty-printers/test-condvar-attributes.c +++ /dev/null @@ -1,94 +0,0 @@ -/* Helper program for testing the pthread_cond_t and pthread_condattr_t - pretty printers. - - Copyright (C) 2016 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/>. */ - -/* Keep the calls to the pthread_* functions on separate lines to make it easy - to advance through the program using the gdb 'next' command. */ - -#include <time.h> -#include <pthread.h> - -#define PASS 0 -#define FAIL 1 - -static int condvar_reinit (pthread_cond_t *condvar, - const pthread_condattr_t *attr); -static int test_setclock (pthread_cond_t *condvar, pthread_condattr_t *attr); -static int test_setpshared (pthread_cond_t *condvar, pthread_condattr_t *attr); - -/* Need these so we don't have lines longer than 79 chars. */ -#define SET_SHARED(attr, shared) pthread_condattr_setpshared (attr, shared) - -int -main (void) -{ - pthread_cond_t condvar; - pthread_condattr_t attr; - int result = FAIL; - - if (pthread_condattr_init (&attr) == 0 - && pthread_cond_init (&condvar, NULL) == 0 - && test_setclock (&condvar, &attr) == PASS - && test_setpshared (&condvar, &attr) == PASS) - result = PASS; - /* Else, one of the pthread_cond* functions failed. */ - - return result; -} - -/* Destroys CONDVAR and re-initializes it using ATTR. */ -static int -condvar_reinit (pthread_cond_t *condvar, const pthread_condattr_t *attr) -{ - int result = FAIL; - - if (pthread_cond_destroy (condvar) == 0 - && pthread_cond_init (condvar, attr) == 0) - result = PASS; - - return result; -} - -/* Tests setting the clock ID attribute. */ -static int -test_setclock (pthread_cond_t *condvar, pthread_condattr_t *attr) -{ - int result = FAIL; - - if (pthread_condattr_setclock (attr, CLOCK_REALTIME) == 0 /* Set clock. */ - && condvar_reinit (condvar, attr) == PASS) - result = PASS; - - return result; -} - -/* Tests setting whether the condvar can be shared between processes. */ -static int -test_setpshared (pthread_cond_t *condvar, pthread_condattr_t *attr) -{ - int result = FAIL; - - if (SET_SHARED (attr, PTHREAD_PROCESS_SHARED) == 0 /* Set shared. */ - && condvar_reinit (condvar, attr) == PASS - && SET_SHARED (attr, PTHREAD_PROCESS_PRIVATE) == 0 - && condvar_reinit (condvar, attr) == PASS) - result = PASS; - - return result; -} diff --git a/pretty-printers/test-condvar-attributes.py b/pretty-printers/test-condvar-attributes.py deleted file mode 100644 index 896feab..0000000 --- a/pretty-printers/test-condvar-attributes.py +++ /dev/null @@ -1,60 +0,0 @@ -# Common tests for the ConditionVariablePrinter and -# ConditionVariableAttributesPrinter classes. -# -# Copyright (C) 2016 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/>. - -import sys - -from test_common import * - -test_source = sys.argv[1] -test_bin = sys.argv[2] -result = PASS - -try: - init_test(test_bin) - go_to_main() - - condvar_var = 'condvar' - condvar_to_string = 'pthread_cond_t' - - attr_var = 'attr' - attr_to_string = 'pthread_condattr_t' - - break_at(test_source, 'Set clock') - continue_cmd() # Go to test_setclock - next_cmd(2) - test_printer(condvar_var, condvar_to_string, {'Clock ID': 'CLOCK_REALTIME'}) - test_printer(attr_var, attr_to_string, {'Clock ID': 'CLOCK_REALTIME'}) - - break_at(test_source, 'Set shared') - continue_cmd() # Go to test_setpshared - next_cmd(2) - test_printer(condvar_var, condvar_to_string, {'Shared': 'Yes'}) - test_printer(attr_var, attr_to_string, {'Shared': 'Yes'}) - next_cmd(2) - test_printer(condvar_var, condvar_to_string, {'Shared': 'No'}) - test_printer(attr_var, attr_to_string, {'Shared': 'No'}) - - continue_cmd() # Exit - -except (NoLineError, pexpect.TIMEOUT) as exception: - print('Error: {0}'.format(exception)) - result = FAIL - -exit(result) diff --git a/pretty-printers/test-condvar-printer.c b/pretty-printers/test-condvar-printer.c deleted file mode 100644 index 0f2a5f4..0000000 --- a/pretty-printers/test-condvar-printer.c +++ /dev/null @@ -1,57 +0,0 @@ -/* Helper program for testing the pthread_cond_t pretty printer. - - Copyright (C) 2016 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/>. */ - -/* Keep the calls to the pthread_* functions on separate lines to make it easy - to advance through the program using the gdb 'next' command. */ - -#include <time.h> -#include <pthread.h> - -#define PASS 0 -#define FAIL 1 - -static int test_status_destroyed (pthread_cond_t *condvar); - -int -main (void) -{ - pthread_cond_t condvar; - pthread_condattr_t attr; - int result = FAIL; - - if (pthread_condattr_init (&attr) == 0 - && test_status_destroyed (&condvar) == PASS) - result = PASS; - /* Else, one of the pthread_cond* functions failed. */ - - return result; -} - -/* Initializes CONDVAR, then destroys it. */ -static int -test_status_destroyed (pthread_cond_t *condvar) -{ - int result = FAIL; - - if (pthread_cond_init (condvar, NULL) == 0 - && pthread_cond_destroy (condvar) == 0) - result = PASS; /* Test status (destroyed). */ - - return result; -} diff --git a/pretty-printers/test-condvar-printer.py b/pretty-printers/test-condvar-printer.py deleted file mode 100644 index 939bbf4..0000000 --- a/pretty-printers/test-condvar-printer.py +++ /dev/null @@ -1,45 +0,0 @@ -# Common tests for the ConditionVariablePrinter class. -# -# Copyright (C) 2016 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/>. - -import sys - -from test_common import * - -test_source = sys.argv[1] -test_bin = sys.argv[2] -result = PASS - -try: - init_test(test_bin) - go_to_main() - - var = 'condvar' - to_string = 'pthread_cond_t' - - break_at(test_source, 'Test status (destroyed)') - continue_cmd() # Go to test_status_destroyed - test_printer(var, to_string, {'Status': 'Destroyed'}) - - continue_cmd() # Exit - -except (NoLineError, pexpect.TIMEOUT) as exception: - print('Error: {0}'.format(exception)) - result = FAIL - -exit(result) diff --git a/pretty-printers/test-mutex-attributes.c b/pretty-printers/test-mutex-attributes.c deleted file mode 100644 index 9ecfff7..0000000 --- a/pretty-printers/test-mutex-attributes.c +++ /dev/null @@ -1,144 +0,0 @@ -/* Helper program for testing the pthread_mutex_t and pthread_mutexattr_t - pretty printers. - - Copyright (C) 2016 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/>. */ - -/* Keep the calls to the pthread_* functions on separate lines to make it easy - to advance through the program using the gdb 'next' command. */ - -#include <pthread.h> - -#define PASS 0 -#define FAIL 1 -#define PRIOCEILING 42 - -/* Need these so we don't have lines longer than 79 chars. */ -#define SET_TYPE(attr, type) pthread_mutexattr_settype (attr, type) -#define SET_ROBUST(attr, robust) pthread_mutexattr_setrobust (attr, robust) -#define SET_SHARED(attr, shared) pthread_mutexattr_setpshared (attr, shared) -#define SET_PROTOCOL(attr, protocol) \ - pthread_mutexattr_setprotocol (attr, protocol) -#define SET_PRIOCEILING(mutex, prioceiling, old_ceiling) \ - pthread_mutex_setprioceiling (mutex, prioceiling, old_ceiling) - -static int mutex_reinit (pthread_mutex_t *mutex, - const pthread_mutexattr_t *attr); -static int test_settype (pthread_mutex_t *mutex, pthread_mutexattr_t *attr); -static int test_setrobust (pthread_mutex_t *mutex, pthread_mutexattr_t *attr); -static int test_setpshared (pthread_mutex_t *mutex, pthread_mutexattr_t *attr); -static int test_setprotocol (pthread_mutex_t *mutex, - pthread_mutexattr_t *attr); - -int -main (void) -{ - pthread_mutex_t mutex; - pthread_mutexattr_t attr; - int result = FAIL; - - if (pthread_mutexattr_init (&attr) == 0 - && pthread_mutex_init (&mutex, NULL) == 0 - && test_settype (&mutex, &attr) == PASS - && test_setrobust (&mutex, &attr) == PASS - && test_setpshared (&mutex, &attr) == PASS - && test_setprotocol (&mutex, &attr) == PASS) - result = PASS; - /* Else, one of the pthread_mutex* functions failed. */ - - return result; -} - -/* Destroys MUTEX and re-initializes it using ATTR. */ -static int -mutex_reinit (pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) -{ - int result = FAIL; - - if (pthread_mutex_destroy (mutex) == 0 - && pthread_mutex_init (mutex, attr) == 0) - result = PASS; - - return result; -} - -/* Tests setting the mutex type. */ -static int -test_settype (pthread_mutex_t *mutex, pthread_mutexattr_t *attr) -{ - int result = FAIL; - - if (SET_TYPE (attr, PTHREAD_MUTEX_ERRORCHECK) == 0 /* Set type. */ - && mutex_reinit (mutex, attr) == 0 - && SET_TYPE (attr, PTHREAD_MUTEX_RECURSIVE) == 0 - && mutex_reinit (mutex, attr) == 0 - && SET_TYPE (attr, PTHREAD_MUTEX_NORMAL) == 0 - && mutex_reinit (mutex, attr) == 0) - result = PASS; - - return result; -} - -/* Tests setting whether the mutex is robust. */ -static int -test_setrobust (pthread_mutex_t *mutex, pthread_mutexattr_t *attr) -{ - int result = FAIL; - - if (SET_ROBUST (attr, PTHREAD_MUTEX_ROBUST) == 0 /* Set robust. */ - && mutex_reinit (mutex, attr) == 0 - && SET_ROBUST (attr, PTHREAD_MUTEX_STALLED) == 0 - && mutex_reinit (mutex, attr) == 0) - result = PASS; - - return result; -} - -/* Tests setting whether the mutex can be shared between processes. */ -static int -test_setpshared (pthread_mutex_t *mutex, pthread_mutexattr_t *attr) -{ - int result = FAIL; - - if (SET_SHARED (attr, PTHREAD_PROCESS_SHARED) == 0 /* Set shared. */ - && mutex_reinit (mutex, attr) == 0 - && SET_SHARED (attr, PTHREAD_PROCESS_PRIVATE) == 0 - && mutex_reinit (mutex, attr) == 0) - result = PASS; - - return result; -} - -/* Tests setting the mutex protocol and, for Priority Protect, the Priority - Ceiling. */ -static int -test_setprotocol (pthread_mutex_t *mutex, pthread_mutexattr_t *attr) -{ - int result = FAIL; - int old_prioceiling; - - if (SET_PROTOCOL (attr, PTHREAD_PRIO_INHERIT) == 0 /* Set protocol. */ - && mutex_reinit (mutex, attr) == 0 - && SET_PROTOCOL (attr, PTHREAD_PRIO_PROTECT) == 0 - && mutex_reinit (mutex, attr) == 0 - && SET_PRIOCEILING(mutex, PRIOCEILING, &old_prioceiling) == 0 - && SET_PROTOCOL (attr, PTHREAD_PRIO_NONE) == 0 - && mutex_reinit (mutex, attr) == 0) - result = PASS; - - return result; -} diff --git a/pretty-printers/test-mutex-attributes.py b/pretty-printers/test-mutex-attributes.py deleted file mode 100644 index 40883ad..0000000 --- a/pretty-printers/test-mutex-attributes.py +++ /dev/null @@ -1,90 +0,0 @@ -# Common tests for the MutexPrinter and MutexAttributesPrinter classes. -# -# Copyright (C) 2016 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/>. - -import sys - -from test_common import * - -test_source = sys.argv[1] -test_bin = sys.argv[2] -result = PASS -PRIOCEILING = 42 - -try: - init_test(test_bin) - go_to_main() - - mutex_var = 'mutex' - mutex_to_string = 'pthread_mutex_t' - - attr_var = 'attr' - attr_to_string = 'pthread_mutexattr_t' - - break_at(test_source, 'Set type') - continue_cmd() # Go to test_settype - next_cmd(2) - test_printer(attr_var, attr_to_string, {'Type': 'Error check'}) - test_printer(mutex_var, mutex_to_string, {'Type': 'Error check'}) - next_cmd(2) - test_printer(attr_var, attr_to_string, {'Type': 'Recursive'}) - test_printer(mutex_var, mutex_to_string, {'Type': 'Recursive'}) - next_cmd(2) - test_printer(attr_var, attr_to_string, {'Type': 'Normal'}) - test_printer(mutex_var, mutex_to_string, {'Type': 'Normal'}) - - break_at(test_source, 'Set robust') - continue_cmd() # Go to test_setrobust - next_cmd(2) - test_printer(attr_var, attr_to_string, {'Robust': 'Yes'}) - test_printer(mutex_var, mutex_to_string, {'Robust': 'Yes'}) - next_cmd(2) - test_printer(attr_var, attr_to_string, {'Robust': 'No'}) - test_printer(mutex_var, mutex_to_string, {'Robust': 'No'}) - - break_at(test_source, 'Set shared') - continue_cmd() # Go to test_setpshared - next_cmd(2) - test_printer(attr_var, attr_to_string, {'Shared': 'Yes'}) - test_printer(mutex_var, mutex_to_string, {'Shared': 'Yes'}) - next_cmd(2) - test_printer(attr_var, attr_to_string, {'Shared': 'No'}) - test_printer(mutex_var, mutex_to_string, {'Shared': 'No'}) - - break_at(test_source, 'Set protocol') - continue_cmd() # Go to test_setprotocol - next_cmd(2) - test_printer(attr_var, attr_to_string, {'Protocol': 'Priority inherit'}) - test_printer(mutex_var, mutex_to_string, {'Protocol': 'Priority inherit'}) - next_cmd(2) - test_printer(attr_var, attr_to_string, {'Protocol': 'Priority protect'}) - test_printer(mutex_var, mutex_to_string, {'Protocol': 'Priority protect'}) - next_cmd(2) - test_printer(mutex_var, mutex_to_string, {'Priority ceiling': - str(PRIOCEILING)}) - next_cmd() - test_printer(attr_var, attr_to_string, {'Protocol': 'None'}) - test_printer(mutex_var, mutex_to_string, {'Protocol': 'None'}) - - continue_cmd() # Exit - -except (NoLineError, pexpect.TIMEOUT) as exception: - print('Error: {0}'.format(exception)) - result = FAIL - -exit(result) diff --git a/pretty-printers/test-mutex-printer.c b/pretty-printers/test-mutex-printer.c deleted file mode 100644 index b973e82..0000000 --- a/pretty-printers/test-mutex-printer.c +++ /dev/null @@ -1,151 +0,0 @@ -/* Helper program for testing the pthread_mutex_t pretty printer. - - Copyright (C) 2016 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/>. */ - -/* Keep the calls to the pthread_* functions on separate lines to make it easy - to advance through the program using the gdb 'next' command. */ - -#include <stdlib.h> -#include <errno.h> -#include <pthread.h> - -#define PASS 0 -#define FAIL 1 - -static int test_status_destroyed (pthread_mutex_t *mutex); -static int test_status_no_robust (pthread_mutex_t *mutex, - pthread_mutexattr_t *attr); -static int test_status_robust (pthread_mutex_t *mutex, - pthread_mutexattr_t *attr); -static int test_locking_state_robust (pthread_mutex_t *mutex); -static void *thread_func (void *arg); -static int test_recursive_locks (pthread_mutex_t *mutex, - pthread_mutexattr_t *attr); - -int -main (void) -{ - pthread_mutex_t mutex; - pthread_mutexattr_t attr; - int result = FAIL; - - if (pthread_mutexattr_init (&attr) == 0 - && test_status_destroyed (&mutex) == PASS - && test_status_no_robust (&mutex, &attr) == PASS - && test_status_robust (&mutex, &attr) == PASS - && test_recursive_locks (&mutex, &attr) == PASS) - result = PASS; - /* Else, one of the pthread_mutex* functions failed. */ - - return result; -} - -/* Initializes MUTEX, then destroys it. */ -static int -test_status_destroyed (pthread_mutex_t *mutex) -{ - int result = FAIL; - - if (pthread_mutex_init (mutex, NULL) == 0 - && pthread_mutex_destroy (mutex) == 0) - result = PASS; /* Test status (destroyed). */ - - return result; -} - -/* Tests locking of non-robust mutexes. */ -static int -test_status_no_robust (pthread_mutex_t *mutex, pthread_mutexattr_t *attr) -{ - int result = FAIL; - - if (pthread_mutexattr_setrobust (attr, PTHREAD_MUTEX_STALLED) == 0 - && pthread_mutex_init (mutex, attr) == 0 - && pthread_mutex_lock (mutex) == 0 /* Test status (non-robust). */ - && pthread_mutex_unlock (mutex) == 0 - && pthread_mutex_destroy (mutex) == 0) - result = PASS; - - return result; -} - -/* Tests locking of robust mutexes. */ -static int -test_status_robust (pthread_mutex_t *mutex, pthread_mutexattr_t *attr) -{ - int result = FAIL; - - if (pthread_mutexattr_setrobust (attr, PTHREAD_MUTEX_ROBUST) == 0 - && pthread_mutex_init (mutex, attr) == 0 - && test_locking_state_robust (mutex) == PASS /* Test status (robust). */ - && pthread_mutex_destroy (mutex) == 0) - result = PASS; - - return result; -} - -/* Tests locking and state corruption of robust mutexes. We'll mark it as - inconsistent, then not recoverable. */ -static int -test_locking_state_robust (pthread_mutex_t *mutex) -{ - int result = FAIL; - pthread_t thread; - - if (pthread_create (&thread, NULL, thread_func, mutex) == 0 /* Create. */ - && pthread_join (thread, NULL) == 0 - && pthread_mutex_lock (mutex) == EOWNERDEAD /* Test locking (robust). */ - && pthread_mutex_unlock (mutex) == 0) - result = PASS; - - return result; -} - -/* Function to be called by the child thread when testing robust mutexes. */ -static void * -thread_func (void *arg) -{ - pthread_mutex_t *mutex = (pthread_mutex_t *)arg; - - if (pthread_mutex_lock (mutex) != 0) /* Thread function. */ - exit (FAIL); - - /* Thread terminates without unlocking the mutex, thus marking it as - inconsistent. */ - return NULL; -} - -/* Tests locking the mutex multiple times in a row. */ -static int -test_recursive_locks (pthread_mutex_t *mutex, pthread_mutexattr_t *attr) -{ - int result = FAIL; - - if (pthread_mutexattr_settype (attr, PTHREAD_MUTEX_RECURSIVE) == 0 - && pthread_mutex_init (mutex, attr) == 0 - && pthread_mutex_lock (mutex) == 0 - && pthread_mutex_lock (mutex) == 0 - && pthread_mutex_lock (mutex) == 0 /* Test recursive locks. */ - && pthread_mutex_unlock (mutex) == 0 - && pthread_mutex_unlock (mutex) == 0 - && pthread_mutex_unlock (mutex) == 0 - && pthread_mutex_destroy (mutex) == 0) - result = PASS; - - return result; -} diff --git a/pretty-printers/test-mutex-printer.py b/pretty-printers/test-mutex-printer.py deleted file mode 100644 index 44f4a48..0000000 --- a/pretty-printers/test-mutex-printer.py +++ /dev/null @@ -1,92 +0,0 @@ -# Tests for the MutexPrinter class. -# -# Copyright (C) 2016 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/>. - -import sys - -from test_common import * - -test_source = sys.argv[1] -test_bin = sys.argv[2] -result = PASS - -try: - init_test(test_bin) - go_to_main() - - var = 'mutex' - to_string = 'pthread_mutex_t' - - break_at(test_source, 'Test status (destroyed)') - continue_cmd() # Go to test_status_destroyed - test_printer(var, to_string, {'Status': 'Destroyed'}) - - break_at(test_source, 'Test status (non-robust)') - continue_cmd() # Go to test_status_no_robust - test_printer(var, to_string, {'Status': 'Unlocked'}) - next_cmd() - thread_id = get_current_thread_lwpid() - test_printer(var, to_string, {'Status': 'Locked, possibly with no waiters', - 'Owner ID': thread_id}) - - break_at(test_source, 'Test status (robust)') - continue_cmd() # Go to test_status_robust - test_printer(var, to_string, {'Status': 'Unlocked'}) - - # We'll now test the robust mutex locking states. We'll create a new - # thread that will lock a robust mutex and exit without unlocking it. - break_at(test_source, 'Create') - continue_cmd() # Go to test_locking_state_robust - # Set a breakpoint for the new thread to hit. - break_at(test_source, 'Thread function') - continue_cmd() - # By now the new thread is created and has hit its breakpoint. - set_scheduler_locking(True) - parent = '1' - child = '2' - select_thread(child) - child_id = get_current_thread_lwpid() - # We've got the new thread's ID. - select_thread(parent) - # Make the new thread finish its function while we wait. - continue_cmd(thread=child) - # The new thread should be dead by now. - break_at(test_source, 'Test locking (robust)') - continue_cmd() - test_printer(var, to_string, {'Owner ID': r'{0} \(dead\)'.format(child_id)}) - # Try to lock and unlock the mutex. - next_cmd() - test_printer(var, to_string, {'Owner ID': thread_id, - 'State protected by this mutex': 'Inconsistent'}) - next_cmd() - test_printer(var, to_string, {'Status': 'Unlocked', - 'State protected by this mutex': 'Not recoverable'}) - set_scheduler_locking(False) - - break_at(test_source, 'Test recursive locks') - continue_cmd() # Go to test_recursive_locks - test_printer(var, to_string, {'Times locked recursively': '2'}) - next_cmd() - test_printer(var, to_string, {'Times locked recursively': '3'}) - continue_cmd() # Exit - -except (NoLineError, pexpect.TIMEOUT) as exception: - print('Error: {0}'.format(exception)) - result = FAIL - -exit(result) diff --git a/pretty-printers/test-rwlock-attributes.c b/pretty-printers/test-rwlock-attributes.c deleted file mode 100644 index d12facf..0000000 --- a/pretty-printers/test-rwlock-attributes.c +++ /dev/null @@ -1,98 +0,0 @@ -/* Helper program for testing the pthread_rwlock_t and pthread_rwlockattr_t - pretty printers. - - Copyright (C) 2016 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/>. */ - -/* Keep the calls to the pthread_* functions on separate lines to make it easy - to advance through the program using the gdb 'next' command. */ - -#include <pthread.h> - -#define PASS 0 -#define FAIL 1 - -/* Need these so we don't have lines longer than 79 chars. */ -#define SET_KIND(attr, kind) pthread_rwlockattr_setkind_np (attr, kind) -#define SET_SHARED(attr, shared) pthread_rwlockattr_setpshared (attr, shared) - -static int rwlock_reinit (pthread_rwlock_t *rwlock, - const pthread_rwlockattr_t *attr); -static int test_setkind_np (pthread_rwlock_t *rwlock, - pthread_rwlockattr_t *attr); -static int test_setpshared (pthread_rwlock_t *rwlock, - pthread_rwlockattr_t *attr); - -int -main (void) -{ - pthread_rwlock_t rwlock; - pthread_rwlockattr_t attr; - int result = FAIL; - - if (pthread_rwlockattr_init (&attr) == 0 - && pthread_rwlock_init (&rwlock, NULL) == 0 - && test_setkind_np (&rwlock, &attr) == PASS - && test_setpshared (&rwlock, &attr) == PASS) - result = PASS; - /* Else, one of the pthread_rwlock* functions failed. */ - - return result; -} - -/* Destroys RWLOCK and re-initializes it using ATTR. */ -static int -rwlock_reinit (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) -{ - int result = FAIL; - - if (pthread_rwlock_destroy (rwlock) == 0 - && pthread_rwlock_init (rwlock, attr) == 0) - result = PASS; - - return result; -} - -/* Tests setting whether the rwlock prefers readers or writers. */ -static int -test_setkind_np (pthread_rwlock_t *rwlock, pthread_rwlockattr_t *attr) -{ - int result = FAIL; - - if (SET_KIND (attr, PTHREAD_RWLOCK_PREFER_READER_NP) == 0 /* Set kind. */ - && rwlock_reinit (rwlock, attr) == PASS - && SET_KIND (attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP) == 0 - && rwlock_reinit (rwlock, attr) == PASS) - result = PASS; - - return result; -} - -/* Tests setting whether the rwlock can be shared between processes. */ -static int -test_setpshared (pthread_rwlock_t *rwlock, pthread_rwlockattr_t *attr) -{ - int result = FAIL; - - if (SET_SHARED (attr, PTHREAD_PROCESS_SHARED) == 0 /* Set shared. */ - && rwlock_reinit (rwlock, attr) == PASS - && SET_SHARED (attr, PTHREAD_PROCESS_PRIVATE) == 0 - && rwlock_reinit (rwlock, attr) == PASS) - result = PASS; - - return result; -} diff --git a/pretty-printers/test-rwlock-attributes.py b/pretty-printers/test-rwlock-attributes.py deleted file mode 100644 index 7655d3d..0000000 --- a/pretty-printers/test-rwlock-attributes.py +++ /dev/null @@ -1,62 +0,0 @@ -# Common tests for the RWLockPrinter and RWLockAttributesPrinter classes. -# -# Copyright (C) 2016 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/>. - -import sys - -from test_common import * - -test_source = sys.argv[1] -test_bin = sys.argv[2] -result = PASS - -try: - init_test(test_bin) - go_to_main() - - rwlock_var = 'rwlock' - rwlock_to_string = 'pthread_rwlock_t' - - attr_var = 'attr' - attr_to_string = 'pthread_rwlockattr_t' - - break_at(test_source, 'Set kind') - continue_cmd() # Go to test_setkind_np - next_cmd(2) - test_printer(rwlock_var, rwlock_to_string, {'Prefers': 'Readers'}) - test_printer(attr_var, attr_to_string, {'Prefers': 'Readers'}) - next_cmd(2) - test_printer(rwlock_var, rwlock_to_string, {'Prefers': 'Writers'}) - test_printer(attr_var, attr_to_string, {'Prefers': 'Writers'}) - - break_at(test_source, 'Set shared') - continue_cmd() # Go to test_setpshared - next_cmd(2) - test_printer(rwlock_var, rwlock_to_string, {'Shared': 'Yes'}) - test_printer(attr_var, attr_to_string, {'Shared': 'Yes'}) - next_cmd(2) - test_printer(rwlock_var, rwlock_to_string, {'Shared': 'No'}) - test_printer(attr_var, attr_to_string, {'Shared': 'No'}) - - continue_cmd() # Exit - -except (NoLineError, pexpect.TIMEOUT) as exception: - print('Error: {0}'.format(exception)) - result = FAIL - -exit(result) diff --git a/pretty-printers/test-rwlock-printer.c b/pretty-printers/test-rwlock-printer.c deleted file mode 100644 index dbbe9b8..0000000 --- a/pretty-printers/test-rwlock-printer.c +++ /dev/null @@ -1,78 +0,0 @@ -/* Helper program for testing the pthread_rwlock_t pretty printer. - - Copyright (C) 2016 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/>. */ - -/* Keep the calls to the pthread_* functions on separate lines to make it easy - to advance through the program using the gdb 'next' command. */ - -#include <pthread.h> - -#define PASS 0 -#define FAIL 1 - -static int test_locking_reader (pthread_rwlock_t *rwlock); -static int test_locking_writer (pthread_rwlock_t *rwlock); - -int -main (void) -{ - pthread_rwlock_t rwlock; - - int result = FAIL; - - if (test_locking_reader (&rwlock) == PASS - && test_locking_writer (&rwlock) == PASS) - result = PASS; - /* Else, one of the pthread_rwlock* functions failed. */ - - return result; -} - -/* Tests locking the rwlock multiple times as a reader. */ -static int -test_locking_reader (pthread_rwlock_t *rwlock) -{ - int result = FAIL; - - if (pthread_rwlock_init (rwlock, NULL) == 0 - && pthread_rwlock_rdlock (rwlock) == 0 /* Test locking (reader). */ - && pthread_rwlock_rdlock (rwlock) == 0 - && pthread_rwlock_rdlock (rwlock) == 0 - && pthread_rwlock_unlock (rwlock) == 0 - && pthread_rwlock_unlock (rwlock) == 0 - && pthread_rwlock_unlock (rwlock) == 0 - && pthread_rwlock_destroy (rwlock) == 0) - result = PASS; - - return result; -} - -/* Tests locking the rwlock as a writer. */ -static int -test_locking_writer (pthread_rwlock_t *rwlock) -{ - int result = FAIL; - - if (pthread_rwlock_init (rwlock, NULL) == 0 - && pthread_rwlock_wrlock (rwlock) == 0 /* Test locking (writer). */ - && pthread_rwlock_unlock (rwlock) == 0 - && pthread_rwlock_destroy (rwlock) == 0) - result = PASS; - - return result; -} diff --git a/pretty-printers/test-rwlock-printer.py b/pretty-printers/test-rwlock-printer.py deleted file mode 100644 index 8820321..0000000 --- a/pretty-printers/test-rwlock-printer.py +++ /dev/null @@ -1,59 +0,0 @@ -# Common tests for the RWLockPrinter class. -# -# Copyright (C) 2016 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/>. - -import sys - -from test_common import * - -test_source = sys.argv[1] -test_bin = sys.argv[2] -result = PASS - -try: - init_test(test_bin) - go_to_main() - - var = 'rwlock' - to_string = 'pthread_rwlock_t' - - break_at(test_source, 'Test locking (reader)') - continue_cmd() # Go to test_locking_reader - test_printer(var, to_string, {'Status': 'Unlocked'}) - next_cmd() - test_printer(var, to_string, {'Status': r'Locked \(Read\)', 'Readers': '1'}) - next_cmd() - test_printer(var, to_string, {'Readers': '2'}) - next_cmd() - test_printer(var, to_string, {'Readers': '3'}) - - break_at(test_source, 'Test locking (writer)') - continue_cmd() # Go to test_locking_writer - test_printer(var, to_string, {'Status': 'Unlocked'}) - next_cmd() - thread_id = get_current_thread_lwpid() - test_printer(var, to_string, {'Status': r'Locked \(Write\)', - 'Writer ID': thread_id}) - - continue_cmd() # Exit - -except (NoLineError, pexpect.TIMEOUT) as exception: - print('Error: {0}'.format(exception)) - result = FAIL - -exit(result) diff --git a/pretty-printers/test_common.py b/pretty-printers/test_common.py deleted file mode 100644 index de758f8..0000000 --- a/pretty-printers/test_common.py +++ /dev/null @@ -1,315 +0,0 @@ -# Common functions and variables for testing the Python pretty printers. -# -# Copyright (C) 2016 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/>. - -"""These tests require PExpect. - -Attributes: - PASS, FAIL, UNSUPPORTED (int): Test exit codes, as per evaluate-test.sh. - GDB (string): A string with the name of the gdb binary. - gdb (pexpect.spawn): The gdb process, as handled by PExpect. - gdb_prompt (raw string): A pattern for matching the gdb prompt. -""" - -import os -import re - -PASS = 0 -FAIL = 1 -UNSUPPORTED = 77 -GDB = 'gdb' - -try: - import pexpect -except ImportError: - print('PExpect must be installed in order to test the pretty printers.') - exit(UNSUPPORTED) - -if not pexpect.which(GDB): - print('gdb must be installed in order to test the pretty printers.') - exit(UNSUPPORTED) - -class NoLineError(Exception): - """Custom exception which indicates that a test file doesn't contain - the requested string. - """ - - def __init__(self, file_name, string): - """Constructor. - - Args: - file_name (string): The name of the test file. - string (string): The string that was requested. - """ - - super(NoLineError, self).__init__() - self.file_name = file_name - self.string = string - - def __str__(self): - """Shows a readable representation of the exception.""" - - return ('File {0} has no line containing the following string: {1}' - .format(self.file_name, self.string)) - -timeout = 1 -TIMEOUTFACTOR = os.environ.get('TIMEOUTFACTOR') - -if TIMEOUTFACTOR: - timeout = int(TIMEOUTFACTOR) - -gdb = pexpect.spawn(GDB, echo=False, timeout=timeout) - -# Set the gdb prompt to a custom one, so that user-defined prompts won't -# interfere. We assume the user won't have his prompt set to this. -gdb_prompt = r'gdb-test% ' -gdb.sendline('set prompt {0}'.format(gdb_prompt)) -gdb.expect(gdb_prompt) - -def test(command, pattern): - """Sends 'command' to gdb and expects the given 'pattern'. - - If 'pattern' is None, simply consumes everything up to and including - the gdb prompt. - - Args: - command (string): The command we'll send to gdb. - pattern (raw string): A pattern the gdb output should match. - - Returns: - string: The string that matched 'pattern', or an empty string if - 'pattern' was None. - """ - - match = '' - - gdb.sendline(command) - - if pattern: - # PExpect does a non-greedy match for '+' and '*'. Since it can't look - # ahead on the gdb output stream, if 'pattern' ends with a '+' or a '*' - # we may end up matching only part of the required output. - # To avoid this, we'll consume 'pattern' and anything that follows it - # up to and including the gdb prompt, then extract 'pattern' later. - index = gdb.expect([r'{0}.+{1}'.format(pattern, gdb_prompt), - pexpect.TIMEOUT]) - - if index == 0: - # gdb.after now contains the whole match. Extract the text that - # matches 'pattern'. - match = re.match(pattern, gdb.after, re.DOTALL).group() - elif index == 1: - # We got a timeout exception. Print information on what caused it - # and bail out. - error = ('Response does not match the expected pattern.\n' - 'Command: {0}\n' - 'Expected pattern: {1}\n' - 'Response: {2}'.format(command, pattern, gdb.before)) - - raise pexpect.TIMEOUT(error) - else: - # Consume just the the gdb prompt. - gdb.expect(gdb_prompt) - - return match - -def init_test(test_bin): - """Loads the test binary file to gdb. - - Args: - test_bin (string): The name of the test binary file. - """ - - test('file {0}'.format(test_bin), None) - -def go_to_main(): - """Executes a gdb 'start' command, which takes us to main.""" - - test('start', r'main') - -def get_line_number(file_name, string): - """Returns the number of the line in which 'string' appears within a file. - - Args: - file_name (string): The name of the file we'll search through. - string (string): The string we'll look for. - - Returns: - int: The number of the line in which 'string' appears, starting from 1. - """ - number = -1 - - with open(file_name) as src_file: - for i, line in enumerate(src_file): - if string in line: - number = i + 1 - break - - if number == -1: - raise NoLineError(file_name, string) - - return number - -def break_at(file_name, string, temporary=True, thread=None): - """Places a breakpoint on the first line in 'file_name' containing 'string'. - - 'string' is usually a comment like "Stop here". Notice this may fail unless - the comment is placed inline next to actual code, e.g.: - - ... - /* Stop here */ - ... - - may fail, while: - - ... - some_func(); /* Stop here */ - ... - - will succeed. - - If 'thread' isn't None, the breakpoint will be set for all the threads. - Otherwise, it'll be set only for 'thread'. - - Args: - file_name (string): The name of the file we'll place the breakpoint in. - string (string): A string we'll look for inside the file. - We'll place a breakpoint on the line which contains it. - temporary (bool): Whether the breakpoint should be automatically deleted - after we reach it. - thread (int): The number of the thread we'll place the breakpoint for, - as seen by gdb. If specified, it should be greater than zero. - """ - - if not thread: - thread_str = '' - else: - thread_str = 'thread {0}'.format(thread) - - if temporary: - command = 'tbreak' - break_type = 'Temporary breakpoint' - else: - command = 'break' - break_type = 'Breakpoint' - - line_number = str(get_line_number(file_name, string)) - - test('{0} {1}:{2} {3}'.format(command, file_name, line_number, thread_str), - r'{0} [0-9]+ at 0x[a-f0-9]+: file {1}, line {2}\.'.format(break_type, - file_name, - line_number)) - -def continue_cmd(thread=None): - """Executes a gdb 'continue' command. - - If 'thread' isn't None, the command will be applied to all the threads. - Otherwise, it'll be applied only to 'thread'. - - Args: - thread (int): The number of the thread we'll apply the command to, - as seen by gdb. If specified, it should be greater than zero. - """ - - if not thread: - command = 'continue' - else: - command = 'thread apply {0} continue'.format(thread) - - test(command, None) - -def next_cmd(count=1, thread=None): - """Executes a gdb 'next' command. - - If 'thread' isn't None, the command will be applied to all the threads. - Otherwise, it'll be applied only to 'thread'. - - Args: - count (int): The 'count' argument of the 'next' command. - thread (int): The number of the thread we'll apply the command to, - as seen by gdb. If specified, it should be greater than zero. - """ - - if not thread: - command = 'next' - else: - command = 'thread apply {0} next' - - test('{0} {1}'.format(command, count), None) - -def select_thread(thread): - """Selects the thread indicated by 'thread'. - - Args: - thread (int): The number of the thread we'll switch to, as seen by gdb. - This should be greater than zero. - """ - - if thread > 0: - test('thread {0}'.format(thread), None) - -def get_current_thread_lwpid(): - """Gets the current thread's Lightweight Process ID. - - Returns: - string: The current thread's LWP ID. - """ - - # It's easier to get the LWP ID through the Python API than the gdb CLI. - command = 'python print(gdb.selected_thread().ptid[1])' - - return test(command, r'[0-9]+') - -def set_scheduler_locking(mode): - """Executes the gdb 'set scheduler-locking' command. - - Args: - mode (bool): Whether the scheduler locking mode should be 'on'. - """ - modes = { - True: 'on', - False: 'off' - } - - test('set scheduler-locking {0}'.format(modes[mode]), None) - -def test_printer(var, to_string, children=None, is_ptr=True): - """ Tests the output of a pretty printer. - - For a variable called 'var', this tests whether its associated printer - outputs the expected 'to_string' and children (if any). - - Args: - var (string): The name of the variable we'll print. - to_string (raw string): The expected output of the printer's 'to_string' - method. - children (map {raw string->raw string}): A map with the expected output - of the printer's children' method. - is_ptr (bool): Whether 'var' is a pointer, and thus should be - dereferenced. - """ - - if is_ptr: - var = '*{0}'.format(var) - - test('print {0}'.format(var), to_string) - - if children: - for name, value in children.items(): - # Children are shown as 'name = value'. - test('print {0}'.format(var), r'{0} = {1}'.format(name, value)) diff --git a/scripts/gen-py-const.awk b/scripts/gen-py-const.awk deleted file mode 100644 index 4586f59..0000000 --- a/scripts/gen-py-const.awk +++ /dev/null @@ -1,118 +0,0 @@ -# Script to generate constants for Python pretty printers. -# -# Copyright (C) 2016 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 script is a smaller version of the clever gen-asm-const.awk hack used to -# generate ASM constants from .sym files. We'll use this to generate constants -# for Python pretty printers. -# -# The input to this script are .pysym files that look like: -# #C_Preprocessor_Directive... -# NAME1 -# NAME2 expression... -# -# A line giving just a name implies an expression consisting of just that name. -# Comments start with '--'. -# -# The output of this script is a 'dummy' function containing 'asm' declarations -# for each non-preprocessor line in the .pysym file. The expression values -# will appear as input operands to the 'asm' declaration. For example, if we -# have: -# -# /* header.h */ -# #define MACRO 42 -# -# struct S { -# char c1; -# char c2; -# char c3; -# }; -# -# enum E { -# ZERO, -# ONE -# }; -# -# /* symbols.pysym */ -# #include <stddef.h> -# #include "header.h" -# -- This is a comment -# MACRO -# C3_OFFSET offsetof(struct S, c3) -# E_ONE ONE -# -# the output will be: -# -# #include <stddef.h> -# #include "header.h" -# void dummy(void) -# { -# asm ("@name@MACRO@value@%0@" : : "i" (MACRO)); -# asm ("@name@C3_OFFSET@value@%0@" : : "i" (offsetof(struct S, c3))); -# asm ("@name@E_ONE@value@%0@" : : "i" (ONE)); -# } -# -# We'll later feed this output to gcc -S. Since '-S' tells gcc to compile but -# not assemble, gcc will output something like: -# -# dummy: -# ... -# @name@MACRO@value@$42@ -# @name@C3_OFFSET@value@$2@ -# @name@E_ONE@value@$1@ -# -# Finally, we can process that output to extract the constant values. -# Notice gcc may prepend a special character such as '$' to each value. - -# found_symbol indicates whether we found a non-comment, non-preprocessor line. -BEGIN { found_symbol = 0 } - -# C preprocessor directives go straight through. -/^#/ { print; next; } - -# Skip comments. -/--/ { next; } - -# Trim leading whitespace. -{ sub(/^[[:blank:]]*/, ""); } - -# If we found a non-comment, non-preprocessor line, print the 'dummy' function -# header. -NF > 0 && !found_symbol { - print "void dummy(void)\n{"; - found_symbol = 1; -} - -# If the line contains just a name, duplicate it so we can use that name -# as the value of the expression. -NF == 1 { sub(/^.*$/, "& &"); } - -# If a line contains a name and an expression... -NF > 1 { - name = $1; - - # Remove any characters before the second field. - sub(/^[^[:blank:]]+[[:blank:]]+/, ""); - - # '$0' ends up being everything that appeared after the first field - # separator. - printf " asm (\"@name@%s@value@%0@\" : : \"i\" (%s));\n", name, $0; -} - -# Close the 'dummy' function. -END { if (found_symbol) print "}"; } |