Skip to content

Commit

Permalink
* sysdeps/powerpc/powerpc32/dl-trampoline.S (_dl_runtime_resolve):
Browse files Browse the repository at this point in the history
	Don't clobber caller's LRSAVE.
	(_dl_prof_resolve): Likewise.
  • Loading branch information
Ulrich Drepper committed Aug 14, 2006
1 parent 107b8a9 commit f17efcb
Show file tree
Hide file tree
Showing 25 changed files with 1,249 additions and 43 deletions.
6 changes: 6 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
2006-08-13 Andreas Schwab <schwab@suse.de>

* sysdeps/powerpc/powerpc32/dl-trampoline.S (_dl_runtime_resolve):
Don't clobber caller's LRSAVE.
(_dl_prof_resolve): Likewise.

2006-08-14 Ulrich Drepper <drepper@redhat.com>

[BZ #1996]
Expand Down
39 changes: 39 additions & 0 deletions nptl/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,42 @@
2006-08-14 Jakub Jelinek <jakub@redhat.com>

* sysdeps/unix/sysv/linux/bits/posix_opt.h
(_POSIX_THREAD_PRIO_PROTECT): Define to 200112L.
* descr.h (struct priority_protection_data): New type.
(struct pthread): Add tpp field.
* pthreadP.h (PTHREAD_MUTEX_PP_NORMAL_NP,
PTHREAD_MUTEX_PP_RECURSIVE_NP, PTHREAD_MUTEX_PP_ERRORCHECK_NP,
PTHREAD_MUTEX_PP_ADAPTIVE_NP): New enum values.
* pthread_mutex_init.c (__pthread_mutex_init): Handle non-robust
TPP mutexes.
* pthread_mutex_lock.c (__pthread_mutex_lock): Handle TPP mutexes.
* pthread_mutex_trylock.c (__pthread_mutex_trylock): Likewise.
* pthread_mutex_timedlock.c (pthread_mutex_timedlock): Likewise.
* pthread_mutex_unlock.c (__pthread_mutex_unlock_usercnt): Likewise.
* tpp.c: New file.
* pthread_setschedparam.c (__pthread_setschedparam): Handle priority
boosted by TPP.
* pthread_setschedprio.c (pthread_setschedprio): Likewise.
* pthread_mutexattr_getprioceiling.c
(pthread_mutexattr_getprioceiling): If ceiling is 0, ensure it is
in the SCHED_FIFO priority range.
* pthread_mutexattr_setprioceiling.c
(pthread_mutexattr_setprioceiling): Fix prioceiling validation.
* pthread_mutex_getprioceiling.c (pthread_mutex_getprioceiling): Fail
if mutex is not TPP. Ceiling is now in __data.__lock.
* pthread_mutex_setprioceiling.c: Include stdbool.h.
(pthread_mutex_setprioceiling): Fix prioceiling validation. Ceiling
is now in __data.__lock. Add locking.
* pthread_create.c (__free_tcb): Free pd->tpp structure.
* Makefile (libpthread-routines): Add tpp.
(xtests): Add tst-mutexpp1, tst-mutexpp6 and tst-mutexpp10.
* tst-tpp.h: New file.
* tst-mutexpp1.c: New file.
* tst-mutexpp6.c: New file.
* tst-mutexpp10.c: New file.
* tst-mutex1.c (TEST_FUNCTION): Don't redefine if already defined.
* tst-mutex6.c (TEST_FUNCTION): Likewise.

2006-08-12 Ulrich Drepper <drepper@redhat.com>

[BZ #2843]
Expand Down
11 changes: 11 additions & 0 deletions nptl/descr.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,14 @@ struct robust_list_head
};


/* Data strcture used to handle thread priority protection. */
struct priority_protection_data
{
int priomax;
unsigned int priomap[];
};


/* Thread descriptor data structure. */
struct pthread
{
Expand Down Expand Up @@ -343,6 +351,9 @@ struct pthread
/* This is what the user specified and what we will report. */
size_t reported_guardsize;

/* Thread Priority Protection data. */
struct priority_protection_data *tpp;

/* Resolver state. */
struct __res_state res;

Expand Down
32 changes: 27 additions & 5 deletions nptl/pthreadP.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,17 +86,31 @@ enum
= PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP,
PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP
= PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP,
PTHREAD_MUTEX_PRIO_PROTECT_NP = 64
PTHREAD_MUTEX_PRIO_PROTECT_NP = 64,
PTHREAD_MUTEX_PP_NORMAL_NP
= PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_NORMAL,
PTHREAD_MUTEX_PP_RECURSIVE_NP
= PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_RECURSIVE_NP,
PTHREAD_MUTEX_PP_ERRORCHECK_NP
= PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_ERRORCHECK_NP,
PTHREAD_MUTEX_PP_ADAPTIVE_NP
= PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_ADAPTIVE_NP
};
#define PTHREAD_MUTEX_PRIO_CEILING_SHIFT 16
#define PTHREAD_MUTEX_PRIO_CEILING_MASK 0x00ff0000

/* Ceiling in __data.__lock. __data.__lock is signed, so don't
use the MSB bit in there, but in the mask also include that bit,
so that the compiler can optimize & PTHREAD_MUTEX_PRIO_CEILING_MASK
masking if the value is then shifted down by
PTHREAD_MUTEX_PRIO_CEILING_SHIFT. */
#define PTHREAD_MUTEX_PRIO_CEILING_SHIFT 19
#define PTHREAD_MUTEX_PRIO_CEILING_MASK 0xfff80000


/* Flags in mutex attr. */
#define PTHREAD_MUTEXATTR_PROTOCOL_SHIFT 28
#define PTHREAD_MUTEXATTR_PROTOCOL_MASK 0x30000000
#define PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT 16
#define PTHREAD_MUTEXATTR_PRIO_CEILING_MASK 0x00ff0000
#define PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT 12
#define PTHREAD_MUTEXATTR_PRIO_CEILING_MASK 0x00fff000
#define PTHREAD_MUTEXATTR_FLAG_ROBUST 0x40000000
#define PTHREAD_MUTEXATTR_FLAG_PSHARED 0x80000000
#define PTHREAD_MUTEXATTR_FLAG_BITS \
Expand Down Expand Up @@ -151,6 +165,14 @@ extern unsigned int __nptl_nthreads attribute_hidden;
extern int __set_robust_list_avail attribute_hidden;
#endif

/* Thread Priority Protection. */
extern int __sched_fifo_min_prio attribute_hidden;
extern int __sched_fifo_max_prio attribute_hidden;
extern void __init_sched_fifo_prio (void) attribute_hidden;
extern int __pthread_tpp_change_priority (int prev_prio, int new_prio)
attribute_hidden;
extern int __pthread_current_priority (void) attribute_hidden;

/* The library can run in debugging mode where it performs a lot more
tests. */
extern int __pthread_debug attribute_hidden;
Expand Down
9 changes: 9 additions & 0 deletions nptl/pthread_create.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,15 @@ __free_tcb (struct pthread *pd)
running thread is gone. */
abort ();

/* Free TPP data. */
if (__builtin_expect (pd->tpp != NULL, 0))
{
struct priority_protection_data *tpp = pd->tpp;

pd->tpp = NULL;
free (tpp);
}

/* Queue the stack memory block for reuse and exit the process. The
kernel will signal via writing to the address returned by
QUEUE-STACK when the stack is available. */
Expand Down
7 changes: 6 additions & 1 deletion nptl/pthread_mutex_getprioceiling.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */

#include <errno.h>
#include <pthreadP.h>


Expand All @@ -26,7 +27,11 @@ pthread_mutex_getprioceiling (mutex, prioceiling)
const pthread_mutex_t *mutex;
int *prioceiling;
{
*prioceiling = (mutex->__data.__kind & PTHREAD_MUTEX_PRIO_CEILING_MASK)
if (__builtin_expect ((mutex->__data.__kind
& PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0, 0))
return EINVAL;

*prioceiling = (mutex->__data.__lock & PTHREAD_MUTEX_PRIO_CEILING_MASK)
>> PTHREAD_MUTEX_PRIO_CEILING_SHIFT;

return 0;
Expand Down
27 changes: 16 additions & 11 deletions nptl/pthread_mutex_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ __pthread_mutex_init (mutex, mutexattr)
imutexattr = (const struct pthread_mutexattr *) mutexattr ?: &default_attr;

/* Sanity checks. */
// XXX For now we don't support priority protected mutexes.
switch (__builtin_expect (imutexattr->mutexkind
& PTHREAD_MUTEXATTR_PROTOCOL_MASK,
PTHREAD_PRIO_NONE
Expand All @@ -72,7 +71,10 @@ __pthread_mutex_init (mutex, mutexattr)
break;

default:
return ENOTSUP;
/* XXX: For now we don't support robust priority protected mutexes. */
if (imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST)
return ENOTSUP;
break;
}

/* Clear the whole variable. */
Expand Down Expand Up @@ -100,15 +102,18 @@ __pthread_mutex_init (mutex, mutexattr)

case PTHREAD_PRIO_PROTECT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_PROTECT_NP;
if (PTHREAD_MUTEX_PRIO_CEILING_MASK
== PTHREAD_MUTEXATTR_PRIO_CEILING_MASK)
mutex->__data.__kind |= (imutexattr->mutexkind
& PTHREAD_MUTEXATTR_PRIO_CEILING_MASK);
else
mutex->__data.__kind |= ((imutexattr->mutexkind
& PTHREAD_MUTEXATTR_PRIO_CEILING_MASK)
>> PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT)
<< PTHREAD_MUTEX_PRIO_CEILING_SHIFT;

int ceiling = (imutexattr->mutexkind
& PTHREAD_MUTEXATTR_PRIO_CEILING_MASK)
>> PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT;
if (! ceiling)
{
if (__sched_fifo_min_prio == -1)
__init_sched_fifo_prio ();
if (ceiling < __sched_fifo_min_prio)
ceiling = __sched_fifo_min_prio;
}
mutex->__data.__lock = ceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
break;

default:
Expand Down
84 changes: 84 additions & 0 deletions nptl/pthread_mutex_lock.c
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,90 @@ __pthread_mutex_lock (mutex)
}
break;

case PTHREAD_MUTEX_PP_RECURSIVE_NP:
case PTHREAD_MUTEX_PP_ERRORCHECK_NP:
case PTHREAD_MUTEX_PP_NORMAL_NP:
case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
{
int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;

oldval = mutex->__data.__lock;

/* Check whether we already hold the mutex. */
if (mutex->__data.__owner == id)
{
if (kind == PTHREAD_MUTEX_ERRORCHECK_NP)
return EDEADLK;

if (kind == PTHREAD_MUTEX_RECURSIVE_NP)
{
/* Just bump the counter. */
if (__builtin_expect (mutex->__data.__count + 1 == 0, 0))
/* Overflow of the counter. */
return EAGAIN;

++mutex->__data.__count;

return 0;
}
}

int oldprio = -1, ceilval;
do
{
int ceiling = (oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK)
>> PTHREAD_MUTEX_PRIO_CEILING_SHIFT;

if (__pthread_current_priority () > ceiling)
{
if (oldprio != -1)
__pthread_tpp_change_priority (oldprio, -1);
return EINVAL;
}

retval = __pthread_tpp_change_priority (oldprio, ceiling);
if (retval)
return retval;

ceilval = ceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
oldprio = ceiling;

oldval
= atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
#ifdef NO_INCR
ceilval | 2,
#else
ceilval | 1,
#endif
ceilval);

if (oldval == ceilval)
break;

do
{
oldval
= atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
ceilval | 2,
ceilval | 1);

if ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval)
break;

if (oldval != ceilval)
lll_futex_wait (&mutex->__data.__lock, ceilval | 2);
}
while (atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
ceilval | 2, ceilval)
!= ceilval);
}
while ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval);

assert (mutex->__data.__owner == 0);
mutex->__data.__count = 1;
}
break;

default:
/* Correct code cannot set any other type. */
return EINVAL;
Expand Down
Loading

0 comments on commit f17efcb

Please sign in to comment.