[BZ #357]
Update. 2004-09-02 Steven Munroe <sjmunroe@us.ibm.com> [BZ #357] * stdlib/tst-setcontext.c (test_stack): Added test for stack clobber. (main): Call test_stack. * sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext.S (__getcontext): Push stack frame then save parms in local frame. Improve instruction scheduling. * sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext.S (__swapcontext): Likewise.
This commit is contained in:
parent
86aca5ac58
commit
73f7c32c47
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
||||||
|
2004-09-02 Steven Munroe <sjmunroe@us.ibm.com>
|
||||||
|
|
||||||
|
[BZ #357]
|
||||||
|
* stdlib/tst-setcontext.c (test_stack): Added test for stack clobber.
|
||||||
|
(main): Call test_stack.
|
||||||
|
* sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext.S
|
||||||
|
(__getcontext): Push stack frame then save parms in local frame.
|
||||||
|
Improve instruction scheduling.
|
||||||
|
* sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext.S
|
||||||
|
(__swapcontext): Likewise.
|
||||||
|
|
||||||
2004-09-01 Andreas Schwab <schwab@suse.de>
|
2004-09-01 Andreas Schwab <schwab@suse.de>
|
||||||
|
|
||||||
* sysdeps/unix/sysv/linux/ia64/sys/ucontext.h [g++ >= 3.5]: Use
|
* sysdeps/unix/sysv/linux/ia64/sys/ucontext.h [g++ >= 3.5]: Use
|
||||||
|
|
|
@ -1,3 +1,62 @@
|
||||||
|
2004-09-02 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
|
* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_cond_t):
|
||||||
|
Rename __data.__clock to __data.__nwaiters, make it unsigned int.
|
||||||
|
* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h (pthread_cond_t):
|
||||||
|
Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S:
|
||||||
|
Decrement __nwaiters. If pthread_cond_destroy has been called and
|
||||||
|
this is the last waiter, signal pthread_cond_destroy caller and
|
||||||
|
avoid using the pthread_cond_t structure after unlock.
|
||||||
|
* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise.
|
||||||
|
Read clock type from the least significant bits of __nwaiters instead
|
||||||
|
of __clock.
|
||||||
|
* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/internaltypes.h: Define COND_CLOCK_BITS.
|
||||||
|
|
||||||
|
2004-08-31 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
|
[BZ #342]
|
||||||
|
* Makefile (tests): Add tst-cond20 and tst-cond21.
|
||||||
|
* tst-cond20.c: New test.
|
||||||
|
* tst-cond21.c: New test.
|
||||||
|
* sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h
|
||||||
|
(pthread_cond_t): Rename __data.__clock to __data.__nwaiters, make
|
||||||
|
it unsigned int.
|
||||||
|
* sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h (pthread_cond_t):
|
||||||
|
Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
|
||||||
|
(pthread_cond_t): Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h (pthread_cond_t):
|
||||||
|
Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h (pthread_cond_t):
|
||||||
|
Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h (pthread_cond_t):
|
||||||
|
Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/lowlevelcond.sym (cond_clock): Remove.
|
||||||
|
(cond_nwaiters): New.
|
||||||
|
(clock_bits): New.
|
||||||
|
* pthread_cond_destroy.c (__pthread_cond_destroy): Return EBUSY
|
||||||
|
if there are waiters not signalled yet.
|
||||||
|
Wait until all already signalled waiters wake up.
|
||||||
|
* sysdeps/pthread/pthread_cond_wait.c (__condvar_cleanup): Decrement
|
||||||
|
__nwaiters. If pthread_cond_destroy has been called and this is the
|
||||||
|
last waiter, signal pthread_cond_destroy caller and avoid using
|
||||||
|
the pthread_cond_t structure after unlock.
|
||||||
|
(__pthread_cond_wait): Increment __nwaiters in the beginning,
|
||||||
|
decrement it when leaving. If pthread_cond_destroy has been called
|
||||||
|
and this is the last waiter, signal pthread_cond_destroy caller.
|
||||||
|
* sysdeps/pthread/pthread_cond_timedwait.c (__pthread_cond_timedwait):
|
||||||
|
Likewise. Read clock type from the least significant bits of
|
||||||
|
__nwaiters instead of __clock.
|
||||||
|
* pthread_condattr_setclock.c (pthread_condattr_setclock): Check
|
||||||
|
whether clock ID can be encoded in COND_CLOCK_BITS bits.
|
||||||
|
* pthread_condattr_getclock.c (pthread_condattr_getclock): Decode
|
||||||
|
clock type just from the last COND_CLOCK_BITS bits of value.
|
||||||
|
* pthread_cond_init.c (__pthread_cond_init): Initialize __nwaiters
|
||||||
|
instead of __clock, just from second bit of condattr's value.
|
||||||
|
|
||||||
2004-08-30 Jakub Jelinek <jakub@redhat.com>
|
2004-08-30 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Include
|
* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Include
|
||||||
|
|
|
@ -193,6 +193,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 \
|
||||||
tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \
|
tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \
|
||||||
tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \
|
tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \
|
||||||
tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \
|
tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \
|
||||||
|
tst-cond20 tst-cond21 \
|
||||||
tst-rwlock1 tst-rwlock2 tst-rwlock3 tst-rwlock4 tst-rwlock5 \
|
tst-rwlock1 tst-rwlock2 tst-rwlock3 tst-rwlock4 tst-rwlock5 \
|
||||||
tst-rwlock6 tst-rwlock7 tst-rwlock8 tst-rwlock9 tst-rwlock10 \
|
tst-rwlock6 tst-rwlock7 tst-rwlock8 tst-rwlock9 tst-rwlock10 \
|
||||||
tst-rwlock11 tst-rwlock12 tst-rwlock13 tst-rwlock14 \
|
tst-rwlock11 tst-rwlock12 tst-rwlock13 tst-rwlock14 \
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
||||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
02111-1307 USA. */
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <shlib-compat.h>
|
#include <shlib-compat.h>
|
||||||
#include "pthreadP.h"
|
#include "pthreadP.h"
|
||||||
|
|
||||||
|
@ -25,6 +26,35 @@ int
|
||||||
__pthread_cond_destroy (cond)
|
__pthread_cond_destroy (cond)
|
||||||
pthread_cond_t *cond;
|
pthread_cond_t *cond;
|
||||||
{
|
{
|
||||||
|
/* Make sure we are alone. */
|
||||||
|
lll_mutex_lock (cond->__data.__lock);
|
||||||
|
|
||||||
|
if (cond->__data.__total_seq > cond->__data.__wakeup_seq)
|
||||||
|
{
|
||||||
|
/* If there are still some waiters which have not been
|
||||||
|
woken up, this is an application bug. */
|
||||||
|
lll_mutex_unlock (cond->__data.__lock);
|
||||||
|
return EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tell pthread_cond_*wait that this condvar is being destroyed. */
|
||||||
|
cond->__data.__total_seq = -1ULL;
|
||||||
|
|
||||||
|
/* If there are waiters which have been already signalled or
|
||||||
|
broadcasted, but still are using the pthread_cond_t structure,
|
||||||
|
pthread_cond_destroy needs to wait for them. */
|
||||||
|
unsigned int nwaiters = cond->__data.__nwaiters;
|
||||||
|
while (nwaiters >= (1 << COND_CLOCK_BITS))
|
||||||
|
{
|
||||||
|
lll_mutex_unlock (cond->__data.__lock);
|
||||||
|
|
||||||
|
lll_futex_wait (&cond->__data.__nwaiters, nwaiters);
|
||||||
|
|
||||||
|
lll_mutex_lock (cond->__data.__lock);
|
||||||
|
|
||||||
|
nwaiters = cond->__data.__nwaiters;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
versioned_symbol (libpthread, __pthread_cond_destroy,
|
versioned_symbol (libpthread, __pthread_cond_destroy,
|
||||||
|
|
|
@ -32,8 +32,9 @@ __pthread_cond_init (cond, cond_attr)
|
||||||
|
|
||||||
cond->__data.__lock = LLL_MUTEX_LOCK_INITIALIZER;
|
cond->__data.__lock = LLL_MUTEX_LOCK_INITIALIZER;
|
||||||
cond->__data.__futex = 0;
|
cond->__data.__futex = 0;
|
||||||
cond->__data.__clock = (icond_attr == NULL
|
cond->__data.__nwaiters = (icond_attr != NULL
|
||||||
? CLOCK_REALTIME : (icond_attr->value & 0xfe) >> 1);
|
&& ((icond_attr->value & (COND_CLOCK_BITS << 1))
|
||||||
|
>> 1));
|
||||||
cond->__data.__total_seq = 0;
|
cond->__data.__total_seq = 0;
|
||||||
cond->__data.__wakeup_seq = 0;
|
cond->__data.__wakeup_seq = 0;
|
||||||
cond->__data.__woken_seq = 0;
|
cond->__data.__woken_seq = 0;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
|
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ pthread_condattr_getclock (attr, clock_id)
|
||||||
const pthread_condattr_t *attr;
|
const pthread_condattr_t *attr;
|
||||||
clockid_t *clock_id;
|
clockid_t *clock_id;
|
||||||
{
|
{
|
||||||
*clock_id = ((((const struct pthread_condattr *) attr)->value) & 0xfe) >> 1;
|
*clock_id = (((((const struct pthread_condattr *) attr)->value) >> 1)
|
||||||
|
& ((1 << COND_CLOCK_BITS) - 1));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
|
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
||||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
02111-1307 USA. */
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
@ -45,8 +46,7 @@ pthread_condattr_setclock (attr, clock_id)
|
||||||
|
|
||||||
INTERNAL_SYSCALL_DECL (err);
|
INTERNAL_SYSCALL_DECL (err);
|
||||||
int val;
|
int val;
|
||||||
val = INTERNAL_SYSCALL (clock_getres, err, 2, CLOCK_MONOTONIC,
|
val = INTERNAL_SYSCALL (clock_getres, err, 2, CLOCK_MONOTONIC, &ts);
|
||||||
&ts);
|
|
||||||
avail = INTERNAL_SYSCALL_ERROR_P (val, err) ? -1 : 1;
|
avail = INTERNAL_SYSCALL_ERROR_P (val, err) ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,11 +57,16 @@ pthread_condattr_setclock (attr, clock_id)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (clock_id != CLOCK_REALTIME)
|
else if (clock_id != CLOCK_REALTIME)
|
||||||
|
/* If more clocks are allowed some day the storing of the clock ID
|
||||||
|
in the pthread_cond_t structure needs to be adjusted. */
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
|
/* Make sure the value fits in the bits we reserved. */
|
||||||
|
assert (clock_id < (1 << COND_CLOCK_BITS));
|
||||||
|
|
||||||
int *valuep = &((struct pthread_condattr *) attr)->value;
|
int *valuep = &((struct pthread_condattr *) attr)->value;
|
||||||
|
|
||||||
*valuep = (*valuep & ~0xfe) | (clock_id << 1);
|
*valuep = (*valuep & ~(1 << (COND_CLOCK_BITS + 1)) & ~1) | (clock_id << 1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,7 @@ __pthread_cond_timedwait (cond, mutex, abstime)
|
||||||
/* We have one new user of the condvar. */
|
/* We have one new user of the condvar. */
|
||||||
++cond->__data.__total_seq;
|
++cond->__data.__total_seq;
|
||||||
++cond->__data.__futex;
|
++cond->__data.__futex;
|
||||||
|
cond->__data.__nwaiters += 1 << COND_CLOCK_BITS;
|
||||||
|
|
||||||
/* Remember the mutex we are using here. If there is already a
|
/* Remember the mutex we are using here. If there is already a
|
||||||
different address store this is a bad user bug. Do not store
|
different address store this is a bad user bug. Do not store
|
||||||
|
@ -98,7 +99,8 @@ __pthread_cond_timedwait (cond, mutex, abstime)
|
||||||
INTERNAL_SYSCALL_DECL (err);
|
INTERNAL_SYSCALL_DECL (err);
|
||||||
int ret;
|
int ret;
|
||||||
ret = INTERNAL_SYSCALL (clock_gettime, err, 2,
|
ret = INTERNAL_SYSCALL (clock_gettime, err, 2,
|
||||||
cond->__data.__clock, &rt);
|
cond->__data.__nwaiters & COND_CLOCK_BITS,
|
||||||
|
&rt);
|
||||||
# ifndef __ASSUME_POSIX_TIMERS
|
# ifndef __ASSUME_POSIX_TIMERS
|
||||||
if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (ret, err), 0))
|
if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (ret, err), 0))
|
||||||
{
|
{
|
||||||
|
@ -185,6 +187,16 @@ __pthread_cond_timedwait (cond, mutex, abstime)
|
||||||
++cond->__data.__woken_seq;
|
++cond->__data.__woken_seq;
|
||||||
|
|
||||||
bc_out:
|
bc_out:
|
||||||
|
|
||||||
|
cond->__data.__nwaiters -= 1 << COND_CLOCK_BITS;
|
||||||
|
|
||||||
|
/* If pthread_cond_destroy was called on this variable already,
|
||||||
|
notify the pthread_cond_destroy caller all waiters have left
|
||||||
|
and it can be successfully destroyed. */
|
||||||
|
if (cond->__data.__total_seq == -1ULL
|
||||||
|
&& cond->__data.__nwaiters < (1 << COND_CLOCK_BITS))
|
||||||
|
lll_futex_wake (&cond->__data.__nwaiters, 1);
|
||||||
|
|
||||||
/* We are done with the condvar. */
|
/* We are done with the condvar. */
|
||||||
lll_mutex_unlock (cond->__data.__lock);
|
lll_mutex_unlock (cond->__data.__lock);
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ __condvar_cleanup (void *arg)
|
||||||
{
|
{
|
||||||
struct _condvar_cleanup_buffer *cbuffer =
|
struct _condvar_cleanup_buffer *cbuffer =
|
||||||
(struct _condvar_cleanup_buffer *) arg;
|
(struct _condvar_cleanup_buffer *) arg;
|
||||||
|
unsigned int destroying;
|
||||||
|
|
||||||
/* We are going to modify shared data. */
|
/* We are going to modify shared data. */
|
||||||
lll_mutex_lock (cbuffer->cond->__data.__lock);
|
lll_mutex_lock (cbuffer->cond->__data.__lock);
|
||||||
|
@ -55,11 +56,25 @@ __condvar_cleanup (void *arg)
|
||||||
++cbuffer->cond->__data.__futex;
|
++cbuffer->cond->__data.__futex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cbuffer->cond->__data.__nwaiters -= 1 << COND_CLOCK_BITS;
|
||||||
|
|
||||||
|
/* If pthread_cond_destroy was called on this variable already,
|
||||||
|
notify the pthread_cond_destroy caller all waiters have left
|
||||||
|
and it can be successfully destroyed. */
|
||||||
|
destroying = 0;
|
||||||
|
if (cbuffer->cond->__data.__total_seq == -1ULL
|
||||||
|
&& cbuffer->cond->__data.__nwaiters < (1 << COND_CLOCK_BITS))
|
||||||
|
{
|
||||||
|
lll_futex_wake (&cbuffer->cond->__data.__nwaiters, 1);
|
||||||
|
destroying = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* We are done. */
|
/* We are done. */
|
||||||
lll_mutex_unlock (cbuffer->cond->__data.__lock);
|
lll_mutex_unlock (cbuffer->cond->__data.__lock);
|
||||||
|
|
||||||
/* Wake everybody to make sure no condvar signal gets lost. */
|
/* Wake everybody to make sure no condvar signal gets lost. */
|
||||||
lll_futex_wake (&cbuffer->cond->__data.__futex, INT_MAX);
|
if (! destroying)
|
||||||
|
lll_futex_wake (&cbuffer->cond->__data.__futex, INT_MAX);
|
||||||
|
|
||||||
/* Get the mutex before returning unless asynchronous cancellation
|
/* Get the mutex before returning unless asynchronous cancellation
|
||||||
is in effect. */
|
is in effect. */
|
||||||
|
@ -90,6 +105,7 @@ __pthread_cond_wait (cond, mutex)
|
||||||
/* We have one new user of the condvar. */
|
/* We have one new user of the condvar. */
|
||||||
++cond->__data.__total_seq;
|
++cond->__data.__total_seq;
|
||||||
++cond->__data.__futex;
|
++cond->__data.__futex;
|
||||||
|
cond->__data.__nwaiters += 1 << COND_CLOCK_BITS;
|
||||||
|
|
||||||
/* Remember the mutex we are using here. If there is already a
|
/* Remember the mutex we are using here. If there is already a
|
||||||
different address store this is a bad user bug. Do not store
|
different address store this is a bad user bug. Do not store
|
||||||
|
@ -145,6 +161,16 @@ __pthread_cond_wait (cond, mutex)
|
||||||
++cond->__data.__woken_seq;
|
++cond->__data.__woken_seq;
|
||||||
|
|
||||||
bc_out:
|
bc_out:
|
||||||
|
|
||||||
|
cond->__data.__nwaiters -= 1 << COND_CLOCK_BITS;
|
||||||
|
|
||||||
|
/* If pthread_cond_destroy was called on this varaible already,
|
||||||
|
notify the pthread_cond_destroy caller all waiters have left
|
||||||
|
and it can be successfully destroyed. */
|
||||||
|
if (cond->__data.__total_seq == -1ULL
|
||||||
|
&& cond->__data.__nwaiters < (1 << COND_CLOCK_BITS))
|
||||||
|
lll_futex_wake (&cond->__data.__nwaiters, 1);
|
||||||
|
|
||||||
/* We are done with the condvar. */
|
/* We are done with the condvar. */
|
||||||
lll_mutex_unlock (cond->__data.__lock);
|
lll_mutex_unlock (cond->__data.__lock);
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ typedef union
|
||||||
unsigned long long int __wakeup_seq;
|
unsigned long long int __wakeup_seq;
|
||||||
unsigned long long int __woken_seq;
|
unsigned long long int __woken_seq;
|
||||||
void *__mutex;
|
void *__mutex;
|
||||||
int __clock;
|
unsigned int __nwaiters;
|
||||||
unsigned int __broadcast_seq;
|
unsigned int __broadcast_seq;
|
||||||
} __data;
|
} __data;
|
||||||
char __size[__SIZEOF_PTHREAD_COND_T];
|
char __size[__SIZEOF_PTHREAD_COND_T];
|
||||||
|
|
|
@ -81,7 +81,7 @@ typedef union
|
||||||
unsigned long long int __wakeup_seq;
|
unsigned long long int __wakeup_seq;
|
||||||
unsigned long long int __woken_seq;
|
unsigned long long int __woken_seq;
|
||||||
void *__mutex;
|
void *__mutex;
|
||||||
int __clock;
|
unsigned int __nwaiters;
|
||||||
unsigned int __broadcast_seq;
|
unsigned int __broadcast_seq;
|
||||||
} __data;
|
} __data;
|
||||||
char __size[__SIZEOF_PTHREAD_COND_T];
|
char __size[__SIZEOF_PTHREAD_COND_T];
|
||||||
|
|
|
@ -87,6 +87,7 @@ __pthread_cond_timedwait:
|
||||||
addl $1, total_seq(%ebx)
|
addl $1, total_seq(%ebx)
|
||||||
adcl $0, total_seq+4(%ebx)
|
adcl $0, total_seq+4(%ebx)
|
||||||
addl $1, cond_futex(%ebx)
|
addl $1, cond_futex(%ebx)
|
||||||
|
addl $(1 << clock_bits), cond_nwaiters(%ebx)
|
||||||
|
|
||||||
#define FRAME_SIZE 24
|
#define FRAME_SIZE 24
|
||||||
subl $FRAME_SIZE, %esp
|
subl $FRAME_SIZE, %esp
|
||||||
|
@ -104,8 +105,9 @@ __pthread_cond_timedwait:
|
||||||
8: movl %ebx, %edx
|
8: movl %ebx, %edx
|
||||||
#ifdef __NR_clock_gettime
|
#ifdef __NR_clock_gettime
|
||||||
/* Get the clock number. */
|
/* Get the clock number. */
|
||||||
movl cond_clock(%ebx), %ebx
|
movl cond_nwaiters(%ebx), %ebx
|
||||||
/* Only clocks 0 and 1 are allowed. Both are handled in the
|
andl $((1 << clock_bits) - 1), %ebx
|
||||||
|
/* Only clocks 0 and 1 are allowed so far. Both are handled in the
|
||||||
kernel. */
|
kernel. */
|
||||||
leal 4(%esp), %ecx
|
leal 4(%esp), %ecx
|
||||||
movl $__NR_clock_gettime, %eax
|
movl $__NR_clock_gettime, %eax
|
||||||
|
@ -226,7 +228,25 @@ __pthread_cond_timedwait:
|
||||||
14: addl $1, woken_seq(%ebx)
|
14: addl $1, woken_seq(%ebx)
|
||||||
adcl $0, woken_seq+4(%ebx)
|
adcl $0, woken_seq+4(%ebx)
|
||||||
|
|
||||||
24: LOCK
|
24: subl $(1 << clock_bits), cond_nwaiters(%ebx)
|
||||||
|
|
||||||
|
/* Wake up a thread which wants to destroy the condvar object. */
|
||||||
|
movl total_seq(%ebx), %eax
|
||||||
|
andl total_seq+4(%ebx), %eax
|
||||||
|
cmpl $0xffffffff, %eax
|
||||||
|
jne 25f
|
||||||
|
movl cond_nwaiters(%ebx), %eax
|
||||||
|
andl $~((1 << clock_bits) - 1), %eax
|
||||||
|
jne 25f
|
||||||
|
|
||||||
|
addl $cond_nwaiters, %ebx
|
||||||
|
movl $SYS_futex, %eax
|
||||||
|
movl $FUTEX_WAKE, %ecx
|
||||||
|
movl $1, %edx
|
||||||
|
ENTER_KERNEL
|
||||||
|
subl $cond_nwaiters, %ebx
|
||||||
|
|
||||||
|
25: LOCK
|
||||||
#if cond_lock == 0
|
#if cond_lock == 0
|
||||||
subl $1, (%ebx)
|
subl $1, (%ebx)
|
||||||
#else
|
#else
|
||||||
|
@ -394,7 +414,27 @@ __condvar_tw_cleanup:
|
||||||
addl $1, woken_seq(%ebx)
|
addl $1, woken_seq(%ebx)
|
||||||
adcl $0, woken_seq+4(%ebx)
|
adcl $0, woken_seq+4(%ebx)
|
||||||
|
|
||||||
3: LOCK
|
3: subl $(1 << clock_bits), cond_nwaiters(%ebx)
|
||||||
|
|
||||||
|
/* Wake up a thread which wants to destroy the condvar object. */
|
||||||
|
xorl %edi, %edi
|
||||||
|
movl total_seq(%ebx), %eax
|
||||||
|
andl total_seq+4(%ebx), %eax
|
||||||
|
cmpl $0xffffffff, %eax
|
||||||
|
jne 4f
|
||||||
|
movl cond_nwaiters(%ebx), %eax
|
||||||
|
andl $~((1 << clock_bits) - 1), %eax
|
||||||
|
jne 4f
|
||||||
|
|
||||||
|
addl $cond_nwaiters, %ebx
|
||||||
|
movl $SYS_futex, %eax
|
||||||
|
movl $FUTEX_WAKE, %ecx
|
||||||
|
movl $1, %edx
|
||||||
|
ENTER_KERNEL
|
||||||
|
subl $cond_nwaiters, %ebx
|
||||||
|
movl $1, %edi
|
||||||
|
|
||||||
|
4: LOCK
|
||||||
#if cond_lock == 0
|
#if cond_lock == 0
|
||||||
subl $1, (%ebx)
|
subl $1, (%ebx)
|
||||||
#else
|
#else
|
||||||
|
@ -410,13 +450,15 @@ __condvar_tw_cleanup:
|
||||||
call __lll_mutex_unlock_wake
|
call __lll_mutex_unlock_wake
|
||||||
|
|
||||||
/* Wake up all waiters to make sure no signal gets lost. */
|
/* Wake up all waiters to make sure no signal gets lost. */
|
||||||
2: addl $cond_futex, %ebx
|
2: testl %edi, %edi
|
||||||
|
jnz 5f
|
||||||
|
addl $cond_futex, %ebx
|
||||||
movl $FUTEX_WAKE, %ecx
|
movl $FUTEX_WAKE, %ecx
|
||||||
movl $SYS_futex, %eax
|
movl $SYS_futex, %eax
|
||||||
movl $0x7fffffff, %edx
|
movl $0x7fffffff, %edx
|
||||||
ENTER_KERNEL
|
ENTER_KERNEL
|
||||||
|
|
||||||
movl 24+FRAME_SIZE(%esp), %eax
|
5: movl 24+FRAME_SIZE(%esp), %eax
|
||||||
call __pthread_mutex_cond_lock
|
call __pthread_mutex_cond_lock
|
||||||
|
|
||||||
movl %esi, (%esp)
|
movl %esi, (%esp)
|
||||||
|
|
|
@ -80,6 +80,7 @@ __pthread_cond_wait:
|
||||||
addl $1, total_seq(%ebx)
|
addl $1, total_seq(%ebx)
|
||||||
adcl $0, total_seq+4(%ebx)
|
adcl $0, total_seq+4(%ebx)
|
||||||
addl $1, cond_futex(%ebx)
|
addl $1, cond_futex(%ebx)
|
||||||
|
addl $(1 << clock_bits), cond_nwaiters(%ebx)
|
||||||
|
|
||||||
#define FRAME_SIZE 16
|
#define FRAME_SIZE 16
|
||||||
subl $FRAME_SIZE, %esp
|
subl $FRAME_SIZE, %esp
|
||||||
|
@ -156,7 +157,25 @@ __pthread_cond_wait:
|
||||||
adcl $0, woken_seq+4(%ebx)
|
adcl $0, woken_seq+4(%ebx)
|
||||||
|
|
||||||
/* Unlock */
|
/* Unlock */
|
||||||
16: LOCK
|
16: subl $(1 << clock_bits), cond_nwaiters(%ebx)
|
||||||
|
|
||||||
|
/* Wake up a thread which wants to destroy the condvar object. */
|
||||||
|
movl total_seq(%ebx), %eax
|
||||||
|
andl total_seq+4(%ebx), %eax
|
||||||
|
cmpl $0xffffffff, %eax
|
||||||
|
jne 17f
|
||||||
|
movl cond_nwaiters(%ebx), %eax
|
||||||
|
andl $~((1 << clock_bits) - 1), %eax
|
||||||
|
jne 17f
|
||||||
|
|
||||||
|
addl $cond_nwaiters, %ebx
|
||||||
|
movl $SYS_futex, %eax
|
||||||
|
movl $FUTEX_WAKE, %ecx
|
||||||
|
movl $1, %edx
|
||||||
|
ENTER_KERNEL
|
||||||
|
subl $cond_nwaiters, %ebx
|
||||||
|
|
||||||
|
17: LOCK
|
||||||
#if cond_lock == 0
|
#if cond_lock == 0
|
||||||
subl $1, (%ebx)
|
subl $1, (%ebx)
|
||||||
#else
|
#else
|
||||||
|
@ -286,7 +305,27 @@ __condvar_w_cleanup:
|
||||||
addl $1, woken_seq(%ebx)
|
addl $1, woken_seq(%ebx)
|
||||||
adcl $0, woken_seq+4(%ebx)
|
adcl $0, woken_seq+4(%ebx)
|
||||||
|
|
||||||
3: LOCK
|
3: subl $(1 << clock_bits), cond_nwaiters(%ebx)
|
||||||
|
|
||||||
|
/* Wake up a thread which wants to destroy the condvar object. */
|
||||||
|
xorl %edi, %edi
|
||||||
|
movl total_seq(%ebx), %eax
|
||||||
|
andl total_seq+4(%ebx), %eax
|
||||||
|
cmpl $0xffffffff, %eax
|
||||||
|
jne 4f
|
||||||
|
movl cond_nwaiters(%ebx), %eax
|
||||||
|
andl $~((1 << clock_bits) - 1), %eax
|
||||||
|
jne 4f
|
||||||
|
|
||||||
|
addl $cond_nwaiters, %ebx
|
||||||
|
movl $SYS_futex, %eax
|
||||||
|
movl $FUTEX_WAKE, %ecx
|
||||||
|
movl $1, %edx
|
||||||
|
ENTER_KERNEL
|
||||||
|
subl $cond_nwaiters, %ebx
|
||||||
|
movl $1, %edi
|
||||||
|
|
||||||
|
4: LOCK
|
||||||
#if cond_lock == 0
|
#if cond_lock == 0
|
||||||
subl $1, (%ebx)
|
subl $1, (%ebx)
|
||||||
#else
|
#else
|
||||||
|
@ -302,13 +341,15 @@ __condvar_w_cleanup:
|
||||||
call __lll_mutex_unlock_wake
|
call __lll_mutex_unlock_wake
|
||||||
|
|
||||||
/* Wake up all waiters to make sure no signal gets lost. */
|
/* Wake up all waiters to make sure no signal gets lost. */
|
||||||
2: addl $cond_futex, %ebx
|
2: testl %edi, %edi
|
||||||
|
jnz 5f
|
||||||
|
addl $cond_futex, %ebx
|
||||||
movl $FUTEX_WAKE, %ecx
|
movl $FUTEX_WAKE, %ecx
|
||||||
movl $SYS_futex, %eax
|
movl $SYS_futex, %eax
|
||||||
movl $0x7fffffff, %edx
|
movl $0x7fffffff, %edx
|
||||||
ENTER_KERNEL
|
ENTER_KERNEL
|
||||||
|
|
||||||
movl 20+FRAME_SIZE(%esp), %eax
|
5: movl 20+FRAME_SIZE(%esp), %eax
|
||||||
call __pthread_mutex_cond_lock
|
call __pthread_mutex_cond_lock
|
||||||
|
|
||||||
movl %esi, (%esp)
|
movl %esi, (%esp)
|
||||||
|
|
|
@ -81,7 +81,7 @@ typedef union
|
||||||
unsigned long long int __wakeup_seq;
|
unsigned long long int __wakeup_seq;
|
||||||
unsigned long long int __woken_seq;
|
unsigned long long int __woken_seq;
|
||||||
void *__mutex;
|
void *__mutex;
|
||||||
int __clock;
|
unsigned int __nwaiters;
|
||||||
unsigned int __broadcast_seq;
|
unsigned int __broadcast_seq;
|
||||||
} __data;
|
} __data;
|
||||||
char __size[__SIZEOF_PTHREAD_COND_T];
|
char __size[__SIZEOF_PTHREAD_COND_T];
|
||||||
|
|
|
@ -75,6 +75,12 @@ struct pthread_condattr
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* The __NWAITERS field is used as a counter and to house the number
|
||||||
|
of bits which represent the clock. COND_CLOCK_BITS is the number
|
||||||
|
of bits reserved for the clock. */
|
||||||
|
#define COND_CLOCK_BITS 1
|
||||||
|
|
||||||
|
|
||||||
/* Read-write lock variable attribute data structure. */
|
/* Read-write lock variable attribute data structure. */
|
||||||
struct pthread_rwlockattr
|
struct pthread_rwlockattr
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <sched.h>
|
||||||
#include <bits/pthreadtypes.h>
|
#include <bits/pthreadtypes.h>
|
||||||
|
#include <internaltypes.h>
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|
||||||
cond_lock offsetof (pthread_cond_t, __data.__lock)
|
cond_lock offsetof (pthread_cond_t, __data.__lock)
|
||||||
cond_futex offsetof (pthread_cond_t, __data.__futex)
|
cond_futex offsetof (pthread_cond_t, __data.__futex)
|
||||||
cond_clock offsetof (pthread_cond_t, __data.__clock)
|
cond_nwaiters offsetof (pthread_cond_t, __data.__nwaiters)
|
||||||
total_seq offsetof (pthread_cond_t, __data.__total_seq)
|
total_seq offsetof (pthread_cond_t, __data.__total_seq)
|
||||||
wakeup_seq offsetof (pthread_cond_t, __data.__wakeup_seq)
|
wakeup_seq offsetof (pthread_cond_t, __data.__wakeup_seq)
|
||||||
woken_seq offsetof (pthread_cond_t, __data.__woken_seq)
|
woken_seq offsetof (pthread_cond_t, __data.__woken_seq)
|
||||||
dep_mutex offsetof (pthread_cond_t, __data.__mutex)
|
dep_mutex offsetof (pthread_cond_t, __data.__mutex)
|
||||||
broadcast_seq offsetof (pthread_cond_t, __data.__broadcast_seq)
|
broadcast_seq offsetof (pthread_cond_t, __data.__broadcast_seq)
|
||||||
|
clock_bits COND_CLOCK_BITS
|
||||||
|
|
|
@ -101,7 +101,7 @@ typedef union
|
||||||
unsigned long long int __wakeup_seq;
|
unsigned long long int __wakeup_seq;
|
||||||
unsigned long long int __woken_seq;
|
unsigned long long int __woken_seq;
|
||||||
void *__mutex;
|
void *__mutex;
|
||||||
int __clock;
|
unsigned int __nwaiters;
|
||||||
unsigned int __broadcast_seq;
|
unsigned int __broadcast_seq;
|
||||||
} __data;
|
} __data;
|
||||||
char __size[__SIZEOF_PTHREAD_COND_T];
|
char __size[__SIZEOF_PTHREAD_COND_T];
|
||||||
|
|
|
@ -100,7 +100,7 @@ typedef union
|
||||||
unsigned long long int __wakeup_seq;
|
unsigned long long int __wakeup_seq;
|
||||||
unsigned long long int __woken_seq;
|
unsigned long long int __woken_seq;
|
||||||
void *__mutex;
|
void *__mutex;
|
||||||
int __clock;
|
unsigned int __nwaiters;
|
||||||
unsigned int __broadcast_seq;
|
unsigned int __broadcast_seq;
|
||||||
} __data;
|
} __data;
|
||||||
char __size[__SIZEOF_PTHREAD_COND_T];
|
char __size[__SIZEOF_PTHREAD_COND_T];
|
||||||
|
|
|
@ -82,7 +82,7 @@ typedef union
|
||||||
unsigned long long int __wakeup_seq;
|
unsigned long long int __wakeup_seq;
|
||||||
unsigned long long int __woken_seq;
|
unsigned long long int __woken_seq;
|
||||||
void *__mutex;
|
void *__mutex;
|
||||||
int __clock;
|
unsigned int __nwaiters;
|
||||||
unsigned int __broadcast_seq;
|
unsigned int __broadcast_seq;
|
||||||
} __data;
|
} __data;
|
||||||
char __size[__SIZEOF_PTHREAD_COND_T];
|
char __size[__SIZEOF_PTHREAD_COND_T];
|
||||||
|
|
|
@ -101,7 +101,7 @@ typedef union
|
||||||
unsigned long long int __wakeup_seq;
|
unsigned long long int __wakeup_seq;
|
||||||
unsigned long long int __woken_seq;
|
unsigned long long int __woken_seq;
|
||||||
void *__mutex;
|
void *__mutex;
|
||||||
int __clock;
|
unsigned int __nwaiters;
|
||||||
unsigned int __broadcast_seq;
|
unsigned int __broadcast_seq;
|
||||||
} __data;
|
} __data;
|
||||||
char __size[__SIZEOF_PTHREAD_COND_T];
|
char __size[__SIZEOF_PTHREAD_COND_T];
|
||||||
|
|
|
@ -100,7 +100,7 @@ typedef union
|
||||||
unsigned long long int __wakeup_seq;
|
unsigned long long int __wakeup_seq;
|
||||||
unsigned long long int __woken_seq;
|
unsigned long long int __woken_seq;
|
||||||
void *__mutex;
|
void *__mutex;
|
||||||
int __clock;
|
int __nwaiters;
|
||||||
unsigned int __broadcast_seq;
|
unsigned int __broadcast_seq;
|
||||||
} __data;
|
} __data;
|
||||||
char __size[__SIZEOF_PTHREAD_COND_T];
|
char __size[__SIZEOF_PTHREAD_COND_T];
|
||||||
|
|
|
@ -111,6 +111,7 @@ __pthread_cond_timedwait:
|
||||||
movq 8(%rsp), %rdi
|
movq 8(%rsp), %rdi
|
||||||
incq total_seq(%rdi)
|
incq total_seq(%rdi)
|
||||||
incl cond_futex(%rdi)
|
incl cond_futex(%rdi)
|
||||||
|
addl $(1 << clock_bits), cond_nwaiters(%rdi)
|
||||||
|
|
||||||
/* Install cancellation handler. */
|
/* Install cancellation handler. */
|
||||||
#ifdef PIC
|
#ifdef PIC
|
||||||
|
@ -135,8 +136,9 @@ __pthread_cond_timedwait:
|
||||||
/* Get the clock number. Note that the field in the condvar
|
/* Get the clock number. Note that the field in the condvar
|
||||||
structure stores the number minus 1. */
|
structure stores the number minus 1. */
|
||||||
movq 8(%rsp), %rdi
|
movq 8(%rsp), %rdi
|
||||||
movl cond_clock(%rdi), %edi
|
movl cond_nwaiters(%rdi), %edi
|
||||||
/* Only clocks 0 and 1 are allowed. Both are handled in the
|
andl $((1 << clock_bits) - 1), %edi
|
||||||
|
/* Only clocks 0 and 1 are allowed so far. Both are handled in the
|
||||||
kernel. */
|
kernel. */
|
||||||
leaq 24(%rsp), %rsi
|
leaq 24(%rsp), %rsi
|
||||||
movq $__NR_clock_gettime, %rax
|
movq $__NR_clock_gettime, %rax
|
||||||
|
@ -244,7 +246,23 @@ __pthread_cond_timedwait:
|
||||||
9: xorq %r14, %r14
|
9: xorq %r14, %r14
|
||||||
14: incq woken_seq(%rdi)
|
14: incq woken_seq(%rdi)
|
||||||
|
|
||||||
24: LOCK
|
24: subl $(1 << clock_bits), cond_nwaiters(%rdi)
|
||||||
|
|
||||||
|
/* Wake up a thread which wants to destroy the condvar object. */
|
||||||
|
cmpq $0xffffffffffffffff, total_seq(%rdi)
|
||||||
|
jne 25f
|
||||||
|
movl cond_nwaiters(%rdi), %eax
|
||||||
|
andl $~((1 << clock_bits) - 1), %eax
|
||||||
|
jne 25f
|
||||||
|
|
||||||
|
addq $cond_nwaiters, %rdi
|
||||||
|
movq $SYS_futex, %rax
|
||||||
|
movq $FUTEX_WAKE, %rsi
|
||||||
|
movl $1, %edx
|
||||||
|
syscall
|
||||||
|
subq $cond_nwaiters, %rdi
|
||||||
|
|
||||||
|
25: LOCK
|
||||||
#if cond_lock == 0
|
#if cond_lock == 0
|
||||||
decl (%rdi)
|
decl (%rdi)
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -40,6 +40,8 @@
|
||||||
.globl __condvar_cleanup
|
.globl __condvar_cleanup
|
||||||
.hidden __condvar_cleanup
|
.hidden __condvar_cleanup
|
||||||
__condvar_cleanup:
|
__condvar_cleanup:
|
||||||
|
pushq %r12
|
||||||
|
|
||||||
/* Get internal lock. */
|
/* Get internal lock. */
|
||||||
movq %rdi, %r8
|
movq %rdi, %r8
|
||||||
movq 8(%rdi), %rdi
|
movq 8(%rdi), %rdi
|
||||||
|
@ -66,12 +68,28 @@ __condvar_cleanup:
|
||||||
jne 3f
|
jne 3f
|
||||||
|
|
||||||
incq wakeup_seq(%rdi)
|
incq wakeup_seq(%rdi)
|
||||||
|
|
||||||
incq woken_seq(%rdi)
|
incq woken_seq(%rdi)
|
||||||
|
|
||||||
incl cond_futex(%rdi)
|
incl cond_futex(%rdi)
|
||||||
|
|
||||||
3: LOCK
|
3: subl $(1 << clock_bits), cond_nwaiters(%rdi)
|
||||||
|
|
||||||
|
/* Wake up a thread which wants to destroy the condvar object. */
|
||||||
|
xorq %r12, %r12
|
||||||
|
cmpq $0xffffffffffffffff, total_seq(%rdi)
|
||||||
|
jne 4f
|
||||||
|
movl cond_nwaiters(%rdi), %eax
|
||||||
|
andl $~((1 << clock_bits) - 1), %eax
|
||||||
|
jne 4f
|
||||||
|
|
||||||
|
addq $cond_nwaiters, %rdi
|
||||||
|
movq $SYS_futex, %rax
|
||||||
|
movq $FUTEX_WAKE, %rsi
|
||||||
|
movl $1, %edx
|
||||||
|
syscall
|
||||||
|
subq $cond_nwaiters, %rdi
|
||||||
|
movq $1, %r12
|
||||||
|
|
||||||
|
4: LOCK
|
||||||
#if cond_lock == 0
|
#if cond_lock == 0
|
||||||
decl (%rdi)
|
decl (%rdi)
|
||||||
#else
|
#else
|
||||||
|
@ -84,15 +102,19 @@ __condvar_cleanup:
|
||||||
callq __lll_mutex_unlock_wake
|
callq __lll_mutex_unlock_wake
|
||||||
|
|
||||||
/* Wake up all waiters to make sure no signal gets lost. */
|
/* Wake up all waiters to make sure no signal gets lost. */
|
||||||
2: addq $cond_futex, %rdi
|
2: testq %r12, %r12
|
||||||
|
jnz 5f
|
||||||
|
addq $cond_futex, %rdi
|
||||||
movq $FUTEX_WAKE, %rsi
|
movq $FUTEX_WAKE, %rsi
|
||||||
movl $0x7fffffff, %edx
|
movl $0x7fffffff, %edx
|
||||||
movq $SYS_futex, %rax
|
movq $SYS_futex, %rax
|
||||||
syscall
|
syscall
|
||||||
|
|
||||||
movq 16(%r8), %rdi
|
5: movq 16(%r8), %rdi
|
||||||
callq __pthread_mutex_cond_lock
|
callq __pthread_mutex_cond_lock
|
||||||
|
|
||||||
|
popq %r12
|
||||||
|
|
||||||
retq
|
retq
|
||||||
.size __condvar_cleanup, .-__condvar_cleanup
|
.size __condvar_cleanup, .-__condvar_cleanup
|
||||||
|
|
||||||
|
@ -157,6 +179,7 @@ __pthread_cond_wait:
|
||||||
movq 8(%rsp), %rdi
|
movq 8(%rsp), %rdi
|
||||||
incq total_seq(%rdi)
|
incq total_seq(%rdi)
|
||||||
incl cond_futex(%rdi)
|
incl cond_futex(%rdi)
|
||||||
|
addl $(1 << clock_bits), cond_nwaiters(%rdi)
|
||||||
|
|
||||||
/* Install cancellation handler. */
|
/* Install cancellation handler. */
|
||||||
#ifdef PIC
|
#ifdef PIC
|
||||||
|
@ -229,7 +252,23 @@ __pthread_cond_wait:
|
||||||
incq woken_seq(%rdi)
|
incq woken_seq(%rdi)
|
||||||
|
|
||||||
/* Unlock */
|
/* Unlock */
|
||||||
16: LOCK
|
16: subl $(1 << clock_bits), cond_nwaiters(%rdi)
|
||||||
|
|
||||||
|
/* Wake up a thread which wants to destroy the condvar object. */
|
||||||
|
cmpq $0xffffffffffffffff, total_seq(%rdi)
|
||||||
|
jne 17f
|
||||||
|
movl cond_nwaiters(%rdi), %eax
|
||||||
|
andl $~((1 << clock_bits) - 1), %eax
|
||||||
|
jne 17f
|
||||||
|
|
||||||
|
addq $cond_nwaiters, %rdi
|
||||||
|
movq $SYS_futex, %rax
|
||||||
|
movq $FUTEX_WAKE, %rsi
|
||||||
|
movl $1, %edx
|
||||||
|
syscall
|
||||||
|
subq $cond_nwaiters, %rdi
|
||||||
|
|
||||||
|
17: LOCK
|
||||||
#if cond_lock == 0
|
#if cond_lock == 0
|
||||||
decl (%rdi)
|
decl (%rdi)
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -0,0 +1,170 @@
|
||||||
|
/* Copyright (C) 2004 Free Software Foundation, Inc.
|
||||||
|
This file is part of the GNU C Library.
|
||||||
|
Contributed by Jakub Jelinek <jakub@redhat.com>, 2004.
|
||||||
|
|
||||||
|
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, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define N 10
|
||||||
|
#define ROUNDS 1000
|
||||||
|
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
|
||||||
|
static pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER;
|
||||||
|
static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
static pthread_barrier_t b;
|
||||||
|
static int count;
|
||||||
|
|
||||||
|
static void *
|
||||||
|
tf (void *p)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < ROUNDS; ++i)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock (&mut);
|
||||||
|
|
||||||
|
if (++count == N)
|
||||||
|
pthread_cond_signal (&cond2);
|
||||||
|
|
||||||
|
#ifdef TIMED
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday (&tv, NULL);
|
||||||
|
struct timespec ts;
|
||||||
|
/* Wait three second. */
|
||||||
|
ts.tv_sec = tv.tv_sec + 3;
|
||||||
|
ts.tv_nsec = tv.tv_usec * 1000;
|
||||||
|
pthread_cond_timedwait (&cond, &mut, &ts);
|
||||||
|
#else
|
||||||
|
pthread_cond_wait (&cond, &mut);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pthread_mutex_unlock (&mut);
|
||||||
|
|
||||||
|
int err = pthread_barrier_wait (&b);
|
||||||
|
if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||||
|
{
|
||||||
|
puts ("child: barrier_wait failed");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = pthread_barrier_wait (&b);
|
||||||
|
if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||||
|
{
|
||||||
|
puts ("child: barrier_wait failed");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
{
|
||||||
|
if (pthread_barrier_init (&b, NULL, N + 1) != 0)
|
||||||
|
{
|
||||||
|
puts ("barrier_init failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock (&mut);
|
||||||
|
|
||||||
|
int i, j, err;
|
||||||
|
pthread_t th[N];
|
||||||
|
for (i = 0; i < N; ++i)
|
||||||
|
if ((err = pthread_create (&th[i], NULL, tf, NULL)) != 0)
|
||||||
|
{
|
||||||
|
printf ("cannot create thread %d: %s\n", i, strerror (err));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ROUNDS; ++i)
|
||||||
|
{
|
||||||
|
pthread_cond_wait (&cond2, &mut);
|
||||||
|
|
||||||
|
if (i & 1)
|
||||||
|
pthread_mutex_unlock (&mut);
|
||||||
|
|
||||||
|
if (i & 2)
|
||||||
|
pthread_cond_broadcast (&cond);
|
||||||
|
else if (i & 4)
|
||||||
|
for (j = 0; j < N; ++j)
|
||||||
|
pthread_cond_signal (&cond);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (j = 0; j < (i / 8) % N; ++j)
|
||||||
|
pthread_cond_signal (&cond);
|
||||||
|
pthread_cond_broadcast (&cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((i & 1) == 0)
|
||||||
|
pthread_mutex_unlock (&mut);
|
||||||
|
|
||||||
|
err = pthread_cond_destroy (&cond);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
printf ("pthread_cond_destroy failed: %s\n", strerror (err));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now clobber the cond variable which has been successfully
|
||||||
|
destroyed above. */
|
||||||
|
memset (&cond, (char) i, sizeof (cond));
|
||||||
|
|
||||||
|
err = pthread_barrier_wait (&b);
|
||||||
|
if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||||
|
{
|
||||||
|
puts ("parent: barrier_wait failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock (&mut);
|
||||||
|
|
||||||
|
err = pthread_barrier_wait (&b);
|
||||||
|
if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||||
|
{
|
||||||
|
puts ("parent: barrier_wait failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
err = pthread_cond_init (&cond, NULL);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
printf ("pthread_cond_init failed: %s\n", strerror (err));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < N; ++i)
|
||||||
|
if ((err = pthread_join (th[i], NULL)) != 0)
|
||||||
|
{
|
||||||
|
printf ("failed to join thread %d: %s\n", i, strerror (err));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
puts ("done");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define TEST_FUNCTION do_test ()
|
||||||
|
#include "../test-skeleton.c"
|
|
@ -0,0 +1,3 @@
|
||||||
|
#include <sys/time.h>
|
||||||
|
#define TIMED 1
|
||||||
|
#include "tst-cond20.c"
|
|
@ -72,6 +72,55 @@ f2 (void)
|
||||||
was_in_f2 = 1;
|
was_in_f2 = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_stack(volatile int a, volatile int b,
|
||||||
|
volatile int c, volatile int d)
|
||||||
|
{
|
||||||
|
volatile int e = 5;
|
||||||
|
volatile int f = 6;
|
||||||
|
ucontext_t uc;
|
||||||
|
|
||||||
|
/* Test for cases where getcontext is clobbering the callers
|
||||||
|
stack, including parameters. */
|
||||||
|
getcontext(&uc);
|
||||||
|
|
||||||
|
if (a != 1)
|
||||||
|
{
|
||||||
|
printf ("%s: getcontext clobbers parm a\n", __FUNCTION__);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b != 2)
|
||||||
|
{
|
||||||
|
printf ("%s: getcontext clobbers parm b\n", __FUNCTION__);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c != 3)
|
||||||
|
{
|
||||||
|
printf ("%s: getcontext clobbers parm c\n", __FUNCTION__);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d != 4)
|
||||||
|
{
|
||||||
|
printf ("%s: getcontext clobbers parm d\n", __FUNCTION__);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e != 5)
|
||||||
|
{
|
||||||
|
printf ("%s: getcontext clobbers varible e\n", __FUNCTION__);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f != 6)
|
||||||
|
{
|
||||||
|
printf ("%s: getcontext clobbers variable f\n", __FUNCTION__);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
volatile int global;
|
volatile int global;
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -88,6 +137,8 @@ main (void)
|
||||||
printf ("%s: getcontext: %m\n", __FUNCTION__);
|
printf ("%s: getcontext: %m\n", __FUNCTION__);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test_stack (1, 2, 3, 4);
|
||||||
|
|
||||||
/* Play some tricks with this context. */
|
/* Play some tricks with this context. */
|
||||||
if (++global == 1)
|
if (++global == 1)
|
||||||
|
|
|
@ -27,18 +27,22 @@
|
||||||
|
|
||||||
.machine "altivec"
|
.machine "altivec"
|
||||||
ENTRY(__getcontext)
|
ENTRY(__getcontext)
|
||||||
|
stwu r1,-16(r1)
|
||||||
|
/* Insure that the _UC_REGS start on a quadword boundary. */
|
||||||
stw r3,_FRAME_PARM_SAVE1(r1)
|
stw r3,_FRAME_PARM_SAVE1(r1)
|
||||||
addi r3,r3,_UC_REG_SPACE+12
|
addi r3,r3,_UC_REG_SPACE+12
|
||||||
clrrwi r3,r3,4
|
clrrwi r3,r3,4
|
||||||
|
|
||||||
|
/* Save the general purpose registers */
|
||||||
stw r0,_UC_GREGS+(PT_R0*4)(r3)
|
stw r0,_UC_GREGS+(PT_R0*4)(r3)
|
||||||
mflr r0
|
mflr r0
|
||||||
stw r1,_UC_GREGS+(PT_R1*4)(r3)
|
stw r2,_UC_GREGS+(PT_R2*4)(r3)
|
||||||
stwu r1,-16(r1)
|
stw r4,_UC_GREGS+(PT_R4*4)(r3)
|
||||||
|
/* Set the callers LR_SAVE, and the ucontext LR and NIP to the callers
|
||||||
|
return address. */
|
||||||
stw r0,_UC_GREGS+(PT_LNK*4)(r3)
|
stw r0,_UC_GREGS+(PT_LNK*4)(r3)
|
||||||
stw r0,_UC_GREGS+(PT_NIP*4)(r3)
|
stw r0,_UC_GREGS+(PT_NIP*4)(r3)
|
||||||
stw r0,_FRAME_LR_SAVE+16(r1)
|
stw r0,_FRAME_LR_SAVE+16(r1)
|
||||||
stw r2,_UC_GREGS+(PT_R2*4)(r3)
|
|
||||||
stw r4,_UC_GREGS+(PT_R4*4)(r3)
|
|
||||||
stw r5,_UC_GREGS+(PT_R5*4)(r3)
|
stw r5,_UC_GREGS+(PT_R5*4)(r3)
|
||||||
stw r6,_UC_GREGS+(PT_R6*4)(r3)
|
stw r6,_UC_GREGS+(PT_R6*4)(r3)
|
||||||
stw r7,_UC_GREGS+(PT_R7*4)(r3)
|
stw r7,_UC_GREGS+(PT_R7*4)(r3)
|
||||||
|
@ -66,23 +70,28 @@ ENTRY(__getcontext)
|
||||||
stw r29,_UC_GREGS+(PT_R29*4)(r3)
|
stw r29,_UC_GREGS+(PT_R29*4)(r3)
|
||||||
stw r30,_UC_GREGS+(PT_R30*4)(r3)
|
stw r30,_UC_GREGS+(PT_R30*4)(r3)
|
||||||
stw r31,_UC_GREGS+(PT_R31*4)(r3)
|
stw r31,_UC_GREGS+(PT_R31*4)(r3)
|
||||||
mfctr r0
|
/* Save the value of R1. We had to push the stack before we
|
||||||
stw r0,_UC_GREGS+(PT_CTR*4)(r3)
|
had the address of uc_reg_space. So compute the address of
|
||||||
mfxer r0
|
the callers stack pointer and save it as R1. */
|
||||||
stw r0,_UC_GREGS+(PT_XER*4)(r3)
|
addi r8,r1,16
|
||||||
mfcr r0
|
|
||||||
stw r0,_UC_GREGS+(PT_CCR*4)(r3)
|
|
||||||
|
|
||||||
/* Set the return value of getcontext to "success". R3 is the only
|
|
||||||
register whose value is not preserved in the saved context. */
|
|
||||||
li r0,0
|
li r0,0
|
||||||
|
/* Save the count, exception and condition registers. */
|
||||||
|
mfctr r11
|
||||||
|
mfxer r10
|
||||||
|
mfcr r9
|
||||||
|
stw r8,_UC_GREGS+(PT_R1*4)(r3)
|
||||||
|
stw r11,_UC_GREGS+(PT_CTR*4)(r3)
|
||||||
|
stw r10,_UC_GREGS+(PT_XER*4)(r3)
|
||||||
|
stw r9,_UC_GREGS+(PT_CCR*4)(r3)
|
||||||
|
/* Set the return value of getcontext to "success". R3 is the only
|
||||||
|
register whose value is not preserved in the saved context. */
|
||||||
stw r0,_UC_GREGS+(PT_R3*4)(r3)
|
stw r0,_UC_GREGS+(PT_R3*4)(r3)
|
||||||
|
|
||||||
/* Zero fill fields that can't be set in user state. */
|
/* Zero fill fields that can't be set in user state. */
|
||||||
stw r0,_UC_GREGS+(PT_MSR*4)(r3)
|
stw r0,_UC_GREGS+(PT_MSR*4)(r3)
|
||||||
stw r0,_UC_GREGS+(PT_MQ*4)(r3)
|
stw r0,_UC_GREGS+(PT_MQ*4)(r3)
|
||||||
|
|
||||||
/* Save the floating-point registers */
|
/* Save the floating-point registers */
|
||||||
stfd fp0,_UC_FREGS+(0*8)(r3)
|
stfd fp0,_UC_FREGS+(0*8)(r3)
|
||||||
stfd fp1,_UC_FREGS+(1*8)(r3)
|
stfd fp1,_UC_FREGS+(1*8)(r3)
|
||||||
stfd fp2,_UC_FREGS+(2*8)(r3)
|
stfd fp2,_UC_FREGS+(2*8)(r3)
|
||||||
|
@ -136,21 +145,31 @@ ENTRY(__getcontext)
|
||||||
lwz r7,_dl_hwcap@l(r7)
|
lwz r7,_dl_hwcap@l(r7)
|
||||||
#endif
|
#endif
|
||||||
andis. r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
|
andis. r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
|
||||||
beq L(no_vec)
|
|
||||||
|
|
||||||
la r10,(_UC_VREGS)(r3)
|
la r10,(_UC_VREGS)(r3)
|
||||||
la r9,(_UC_VREGS+16)(r3)
|
la r9,(_UC_VREGS+16)(r3)
|
||||||
|
|
||||||
|
beq L(no_vec)
|
||||||
|
/* address of the combined VSCR/VSAVE quadword. */
|
||||||
|
la r8,(_UC_VREGS+512)(r3)
|
||||||
|
|
||||||
|
/* Save the vector registers */
|
||||||
stvx v0,0,r10
|
stvx v0,0,r10
|
||||||
stvx v1,0,r9
|
stvx v1,0,r9
|
||||||
addi r10,r10,32
|
addi r10,r10,32
|
||||||
addi r9,r9,32
|
addi r9,r9,32
|
||||||
|
/* We need to get the Vector Status and Control Register early to avoid
|
||||||
|
store order problems later with the VSAVE register that shares the
|
||||||
|
same quadword. */
|
||||||
|
mfvscr v0
|
||||||
|
|
||||||
stvx v2,0,r10
|
stvx v2,0,r10
|
||||||
stvx v3,0,r9
|
stvx v3,0,r9
|
||||||
addi r10,r10,32
|
addi r10,r10,32
|
||||||
addi r9,r9,32
|
addi r9,r9,32
|
||||||
|
|
||||||
|
stvx v0,0,r8
|
||||||
|
|
||||||
stvx v4,0,r10
|
stvx v4,0,r10
|
||||||
stvx v5,0,r9
|
stvx v5,0,r9
|
||||||
addi r10,r10,32
|
addi r10,r10,32
|
||||||
|
@ -216,20 +235,18 @@ ENTRY(__getcontext)
|
||||||
addi r10,r10,32
|
addi r10,r10,32
|
||||||
addi r9,r9,32
|
addi r9,r9,32
|
||||||
|
|
||||||
|
mfspr r0,VRSAVE
|
||||||
stvx v30,0,r10
|
stvx v30,0,r10
|
||||||
stvx v31,0,r9
|
stvx v31,0,r9
|
||||||
addi r10,r10,32
|
|
||||||
addi r9,r9,32
|
|
||||||
|
|
||||||
mfvscr v0
|
stw r0,0(r8)
|
||||||
mfspr r0,VRSAVE
|
|
||||||
stvx v0,0,r10
|
|
||||||
sync
|
|
||||||
stw r0,0(r10)
|
|
||||||
|
|
||||||
L(no_vec):
|
L(no_vec):
|
||||||
/* Restore ucontext (parm1) from stack. */
|
/* We need to set up parms and call sigprocmask which will clobber
|
||||||
lwz r12,_FRAME_PARM_SAVE1+16(r1)
|
volatile registers. So before the call we need to retrieve the
|
||||||
|
original ucontext ptr (parm1) from stack and store the UC_REGS_PTR
|
||||||
|
(current R3). */
|
||||||
|
lwz r12,_FRAME_PARM_SAVE1(r1)
|
||||||
li r4,0
|
li r4,0
|
||||||
stw r3,_UC_REGS_PTR(r12)
|
stw r3,_UC_REGS_PTR(r12)
|
||||||
addi r5,r12,_UC_SIGMASK
|
addi r5,r12,_UC_SIGMASK
|
||||||
|
|
|
@ -27,22 +27,23 @@
|
||||||
|
|
||||||
.machine "altivec"
|
.machine "altivec"
|
||||||
ENTRY(__swapcontext)
|
ENTRY(__swapcontext)
|
||||||
/* Save the current context */
|
stwu r1,-16(r1)
|
||||||
|
/* Insure that the _UC_REGS start on a quadword boundary. */
|
||||||
stw r3,_FRAME_PARM_SAVE1(r1)
|
stw r3,_FRAME_PARM_SAVE1(r1)
|
||||||
addi r3,r3,_UC_REG_SPACE+12
|
addi r3,r3,_UC_REG_SPACE+12
|
||||||
|
stw r4,_FRAME_PARM_SAVE2(r1) /* new context pointer */
|
||||||
clrrwi r3,r3,4
|
clrrwi r3,r3,4
|
||||||
|
|
||||||
|
/* Save the general purpose registers */
|
||||||
stw r0,_UC_GREGS+(PT_R0*4)(r3)
|
stw r0,_UC_GREGS+(PT_R0*4)(r3)
|
||||||
stw r1,_UC_GREGS+(PT_R1*4)(r3)
|
|
||||||
mflr r0
|
mflr r0
|
||||||
stwu r1,-16(r1)
|
stw r2,_UC_GREGS+(PT_R2*4)(r3)
|
||||||
stw r0,20(r1)
|
stw r4,_UC_GREGS+(PT_R4*4)(r3)
|
||||||
stw r31,12(r1)
|
/* Set the callers LR_SAVE, and the ucontext LR and NIP to the callers
|
||||||
stw r31,_UC_GREGS+(PT_R31*4)(r3)
|
return address. */
|
||||||
mr r31,r4 /* new context pointer */
|
|
||||||
stw r0,_UC_GREGS+(PT_LNK*4)(r3)
|
stw r0,_UC_GREGS+(PT_LNK*4)(r3)
|
||||||
stw r0,_UC_GREGS+(PT_NIP*4)(r3)
|
stw r0,_UC_GREGS+(PT_NIP*4)(r3)
|
||||||
stw r2,_UC_GREGS+(PT_R2*4)(r3)
|
stw r0,_FRAME_LR_SAVE+16(r1)
|
||||||
stw r4,_UC_GREGS+(PT_R4*4)(r3)
|
|
||||||
stw r5,_UC_GREGS+(PT_R5*4)(r3)
|
stw r5,_UC_GREGS+(PT_R5*4)(r3)
|
||||||
stw r6,_UC_GREGS+(PT_R6*4)(r3)
|
stw r6,_UC_GREGS+(PT_R6*4)(r3)
|
||||||
stw r7,_UC_GREGS+(PT_R7*4)(r3)
|
stw r7,_UC_GREGS+(PT_R7*4)(r3)
|
||||||
|
@ -69,16 +70,23 @@ ENTRY(__swapcontext)
|
||||||
stw r28,_UC_GREGS+(PT_R28*4)(r3)
|
stw r28,_UC_GREGS+(PT_R28*4)(r3)
|
||||||
stw r29,_UC_GREGS+(PT_R29*4)(r3)
|
stw r29,_UC_GREGS+(PT_R29*4)(r3)
|
||||||
stw r30,_UC_GREGS+(PT_R30*4)(r3)
|
stw r30,_UC_GREGS+(PT_R30*4)(r3)
|
||||||
mfctr r0
|
stw r31,_UC_GREGS+(PT_R31*4)(r3)
|
||||||
stw r0,_UC_GREGS+(PT_CTR*4)(r3)
|
|
||||||
mfxer r0
|
/* Save the value of R1. We had to push the stack before we
|
||||||
stw r0,_UC_GREGS+(PT_XER*4)(r3)
|
had the address of uc_reg_space. So compute the address of
|
||||||
mfcr r0
|
the callers stack pointer and save it as R1. */
|
||||||
stw r0,_UC_GREGS+(PT_CCR*4)(r3)
|
addi r8,r1,16
|
||||||
|
|
||||||
/* Set the return value of swapcontext to "success". R3 is the only
|
|
||||||
register whose value is not preserved in the saved context. */
|
|
||||||
li r0,0
|
li r0,0
|
||||||
|
/* Save the count, exception and condition registers. */
|
||||||
|
mfctr r11
|
||||||
|
mfxer r10
|
||||||
|
mfcr r9
|
||||||
|
stw r8,_UC_GREGS+(PT_R1*4)(r3)
|
||||||
|
stw r11,_UC_GREGS+(PT_CTR*4)(r3)
|
||||||
|
stw r10,_UC_GREGS+(PT_XER*4)(r3)
|
||||||
|
stw r9,_UC_GREGS+(PT_CCR*4)(r3)
|
||||||
|
/* Set the return value of getcontext to "success". R3 is the only
|
||||||
|
register whose value is not preserved in the saved context. */
|
||||||
stw r0,_UC_GREGS+(PT_R3*4)(r3)
|
stw r0,_UC_GREGS+(PT_R3*4)(r3)
|
||||||
|
|
||||||
/* Zero fill fields that can't be set in user state. */
|
/* Zero fill fields that can't be set in user state. */
|
||||||
|
@ -138,20 +146,30 @@ ENTRY(__swapcontext)
|
||||||
lwz r7,_dl_hwcap@l(r7)
|
lwz r7,_dl_hwcap@l(r7)
|
||||||
#endif
|
#endif
|
||||||
andis. r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
|
andis. r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
|
||||||
beq L(no_vec)
|
|
||||||
|
|
||||||
la r10,(_UC_VREGS)(r3)
|
la r10,(_UC_VREGS)(r3)
|
||||||
la r9,(_UC_VREGS+16)(r3)
|
la r9,(_UC_VREGS+16)(r3)
|
||||||
|
|
||||||
|
beq L(no_vec)
|
||||||
|
/* address of the combined VSCR/VSAVE quadword. */
|
||||||
|
la r8,(_UC_VREGS+512)(r3)
|
||||||
|
|
||||||
|
/* Save the vector registers */
|
||||||
stvx v0,0,r10
|
stvx v0,0,r10
|
||||||
stvx v1,0,r9
|
stvx v1,0,r9
|
||||||
addi r10,r10,32
|
addi r10,r10,32
|
||||||
addi r9,r9,32
|
addi r9,r9,32
|
||||||
|
/* We need to get the Vector Status and Control Register early to avoid
|
||||||
|
store order problems later with the VSAVE register that shares the
|
||||||
|
same quadword. */
|
||||||
|
mfvscr v0
|
||||||
|
|
||||||
stvx v2,0,r10
|
stvx v2,0,r10
|
||||||
stvx v3,0,r9
|
stvx v3,0,r9
|
||||||
addi r10,r10,32
|
addi r10,r10,32
|
||||||
addi r9,r9,32
|
addi r9,r9,32
|
||||||
|
|
||||||
|
stvx v0,0,r8
|
||||||
|
|
||||||
stvx v4,0,r10
|
stvx v4,0,r10
|
||||||
stvx v5,0,r9
|
stvx v5,0,r9
|
||||||
|
@ -218,20 +236,15 @@ ENTRY(__swapcontext)
|
||||||
addi r10,r10,32
|
addi r10,r10,32
|
||||||
addi r9,r9,32
|
addi r9,r9,32
|
||||||
|
|
||||||
|
mfvscr v0
|
||||||
stvx v30,0,r10
|
stvx v30,0,r10
|
||||||
stvx v31,0,r9
|
stvx v31,0,r9
|
||||||
addi r10,r10,32
|
|
||||||
addi r9,r9,32
|
|
||||||
|
|
||||||
mfvscr v0
|
stw r0,0(r8)
|
||||||
mfspr r0,VRSAVE
|
|
||||||
stvx v0,0,r10
|
|
||||||
sync
|
|
||||||
stw r0,0(r10)
|
|
||||||
|
|
||||||
L(no_vec):
|
L(no_vec):
|
||||||
/* Restore ucontext (parm1) from stack. */
|
/* Restore ucontext (parm1) from stack. */
|
||||||
lwz r12,_FRAME_PARM_SAVE1+16(r1)
|
lwz r12,_FRAME_PARM_SAVE1(r1)
|
||||||
li r4,0
|
li r4,0
|
||||||
stw r3,_UC_REGS_PTR(r12)
|
stw r3,_UC_REGS_PTR(r12)
|
||||||
addi r5,r12,_UC_SIGMASK
|
addi r5,r12,_UC_SIGMASK
|
||||||
|
@ -251,8 +264,8 @@ L(no_vec):
|
||||||
* r0, xer, ctr. We don't restore r2 since it will be used as
|
* r0, xer, ctr. We don't restore r2 since it will be used as
|
||||||
* the TLS pointer.
|
* the TLS pointer.
|
||||||
*/
|
*/
|
||||||
mr r4,r31
|
lwz r4,_FRAME_PARM_SAVE2(r1)
|
||||||
lwz r31,_UC_REGS_PTR(r31)
|
lwz r31,_UC_REGS_PTR(r4)
|
||||||
lwz r0,_UC_GREGS+(PT_MSR*4)(r31)
|
lwz r0,_UC_GREGS+(PT_MSR*4)(r31)
|
||||||
cmpwi r0,0
|
cmpwi r0,0
|
||||||
bne L(do_sigret)
|
bne L(do_sigret)
|
||||||
|
@ -451,8 +464,7 @@ L(has_no_vec):
|
||||||
bctr
|
bctr
|
||||||
|
|
||||||
L(error_exit):
|
L(error_exit):
|
||||||
lwz r31,12(r1)
|
lwz r0,_FRAME_LR_SAVE+16(r1)
|
||||||
lwz r0,20(r1)
|
|
||||||
addi r1,r1,16
|
addi r1,r1,16
|
||||||
mtlr r0
|
mtlr r0
|
||||||
blr
|
blr
|
||||||
|
|
Loading…
Reference in New Issue