mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-22 02:40:08 +00:00
Update.
2003-02-05 Ulrich Drepper <drepper@redhat.com> * sysdeps/pthread/bits/libc-lock.h (__libc_once): Set control variable for non-libpthread case to the same value the pthread_once function would use.
This commit is contained in:
parent
ec609a8e77
commit
a88c926368
@ -1,3 +1,9 @@
|
||||
2003-02-05 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* sysdeps/pthread/bits/libc-lock.h (__libc_once): Set control
|
||||
variable for non-libpthread case to the same value the
|
||||
pthread_once function would use.
|
||||
|
||||
2003-02-03 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S (__vfork): If
|
||||
|
@ -224,7 +224,7 @@ typedef pthread_key_t __libc_key_t;
|
||||
__pthread_once (&(ONCE_CONTROL), (INIT_FUNCTION)); \
|
||||
else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \
|
||||
INIT_FUNCTION (); \
|
||||
(ONCE_CONTROL) = !PTHREAD_ONCE_INIT; \
|
||||
(ONCE_CONTROL) = 2; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
@ -1,3 +1,54 @@
|
||||
2003-02-04 Martin Schwidefsky <schwidefsky@de.ibm.com>
|
||||
|
||||
* sysdeps/unix/sysv/linux/s390/fork.c: Correct order of parameters.
|
||||
|
||||
2003-01-31 Martin Schwidefsky <schwidefsky@de.ibm.com>
|
||||
|
||||
* init.c (__NR_set_tid_address): Add #ifdef for s390.
|
||||
* sysdeps/pthread/pthread_barrier_wait.c: New file.
|
||||
* sysdeps/pthread/pthread_cond_broadcast.c: New file.
|
||||
* sysdeps/pthread/pthread_cond_signal.c: New file.
|
||||
* sysdeps/pthread/pthread_cond_timedwait.c: New file.
|
||||
* sysdeps/pthread/pthread_cond_wait.c: New file.
|
||||
* sysdeps/pthread/pthread_rwlock_rdlock.c: New file.
|
||||
* sysdeps/pthread/pthread_rwlock_timedrdlock.c: New file.
|
||||
* sysdeps/pthread/pthread_rwlock_timedwrlock.c: New file.
|
||||
* sysdeps/pthread/pthread_rwlock_unlock.c: New file.
|
||||
* sysdeps/pthread/pthread_rwlock_wrlock.c: New file.
|
||||
* sysdeps/s390/Makefile: New file.
|
||||
* sysdeps/s390/bits/atomic.h: New file.
|
||||
* sysdeps/s390/pthread_spin_init.c: New file.
|
||||
* sysdeps/s390/pthread_spin_lock.c: New file.
|
||||
* sysdeps/s390/pthread_spin_trylock.c: New file.
|
||||
* sysdeps/s390/pthread_spin_unlock.c: New file.
|
||||
* sysdeps/s390/pthreaddef.h: New file.
|
||||
* sysdeps/s390/tcb-offsets.sym: New file.
|
||||
* sysdeps/s390/td_ta_map_lwp2thr.c: New file.
|
||||
* sysdeps/s390/tls.h: New file.
|
||||
* sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: New file.
|
||||
* sysdeps/unix/sysv/linux/s390/bits/semaphore.h: New file.
|
||||
* sysdeps/unix/sysv/linux/s390/createthread.c: New file.
|
||||
* sysdeps/unix/sysv/linux/s390/dl-sysdep.h: New file.
|
||||
* sysdeps/unix/sysv/linux/s390/fork.c: New file.
|
||||
* sysdeps/unix/sysv/linux/s390/jmp-unwind.c: New file.
|
||||
* sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c: New file.
|
||||
* sysdeps/unix/sysv/linux/s390/libc-lowlevelmutex.c: New file.
|
||||
* sysdeps/unix/sysv/linux/s390/lowlevellock.c: New file.
|
||||
* sysdeps/unix/sysv/linux/s390/lowlevellock.h: New file.
|
||||
* sysdeps/unix/sysv/linux/s390/lowlevelmutex.c: New file.
|
||||
* sysdeps/unix/sysv/linux/s390/lowlevelsem.h: New file.
|
||||
* sysdeps/unix/sysv/linux/s390/pthread_once.c: New file.
|
||||
* sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c: New file.
|
||||
* sysdeps/unix/sysv/linux/s390/s390-32/pt-vfork.S: New file.
|
||||
* sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h: New file.
|
||||
* sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c: New file.
|
||||
* sysdeps/unix/sysv/linux/s390/s390-64/pt-vfork.S: New file.
|
||||
* sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h: New file.
|
||||
* sysdeps/unix/sysv/linux/s390/sem_post.c: New file.
|
||||
* sysdeps/unix/sysv/linux/s390/sem_timedwait.c: New file.
|
||||
* sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c: New file.
|
||||
* sysdeps/unix/sysv/linux/s390/sem_wait.c: New file.
|
||||
|
||||
2003-02-04 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* atomic.h: Add a couple more default implementations.
|
||||
|
@ -194,7 +194,7 @@ queue_stack (struct pthread *stack)
|
||||
{
|
||||
struct pthread *curr;
|
||||
|
||||
curr = list_entry(entry, struct pthread, header.data.list);
|
||||
curr = list_entry (entry, struct pthread, header.data.list);
|
||||
if (FREE_P (curr))
|
||||
{
|
||||
/* Unlink the block. */
|
||||
|
@ -33,8 +33,13 @@
|
||||
#include <shlib-compat.h>
|
||||
|
||||
|
||||
/* XXX For the time being... */
|
||||
#define __NR_set_tid_address 258
|
||||
/* XXX For the time being... Once we can rely on the kernel headers
|
||||
having the definition remove these lines. */
|
||||
#if defined __s390__
|
||||
# define __NR_set_tid_address 252
|
||||
#else
|
||||
# define __NR_set_tid_address 258
|
||||
#endif
|
||||
|
||||
|
||||
/* Default stack size. */
|
||||
|
79
nptl/sysdeps/pthread/pthread_barrier_wait.c
Normal file
79
nptl/sysdeps/pthread/pthread_barrier_wait.c
Normal file
@ -0,0 +1,79 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 <errno.h>
|
||||
#include <sysdep.h>
|
||||
#include <lowlevellock.h>
|
||||
#include <pthreadP.h>
|
||||
|
||||
|
||||
/* Wait on barrier. */
|
||||
int
|
||||
pthread_barrier_wait (barrier)
|
||||
pthread_barrier_t *barrier;
|
||||
{
|
||||
struct pthread_barrier *ibarrier = (struct pthread_barrier *) barrier;
|
||||
|
||||
/* Make sure we are alone. */
|
||||
lll_lock (ibarrier->lock);
|
||||
|
||||
/* One more arrival. */
|
||||
--ibarrier->left;
|
||||
|
||||
/* Are these all? */
|
||||
if (ibarrier->left == 0)
|
||||
{
|
||||
/* Yes. Restore the barrier to be empty. */
|
||||
ibarrier->left = ibarrier->init_count;
|
||||
|
||||
/* Increment the event counter to avoid invalid wake-ups and
|
||||
tell the current waiters that it is their turn. */
|
||||
++ibarrier->curr_event;
|
||||
|
||||
/* Wake up everybody. */
|
||||
lll_futex_wake (&ibarrier->curr_event, INT_MAX);
|
||||
|
||||
/* The barrier is open for business again. */
|
||||
lll_unlock (ibarrier->lock);
|
||||
|
||||
/* This is the thread which finished the serialization. */
|
||||
return PTHREAD_BARRIER_SERIAL_THREAD;
|
||||
}
|
||||
|
||||
/* The number of the event we are waiting for. The barrier's event
|
||||
number must be bumped before we continue. */
|
||||
unsigned int event = ibarrier->curr_event;
|
||||
do
|
||||
{
|
||||
/* Before suspending, make the barrier available to others. */
|
||||
lll_unlock (ibarrier->lock);
|
||||
|
||||
/* Wait for the event counter of the barrier to change. */
|
||||
lll_futex_wait (&ibarrier->curr_event, event);
|
||||
|
||||
/* We are going to access shared data. */
|
||||
lll_lock (ibarrier->lock);
|
||||
}
|
||||
while (event == ibarrier->curr_event);
|
||||
|
||||
/* We are done, let others use the barrier. */
|
||||
lll_unlock (ibarrier->lock);
|
||||
|
||||
return 0;
|
||||
}
|
64
nptl/sysdeps/pthread/pthread_cond_broadcast.c
Normal file
64
nptl/sysdeps/pthread/pthread_cond_broadcast.c
Normal file
@ -0,0 +1,64 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 <endian.h>
|
||||
#include <errno.h>
|
||||
#include <sysdep.h>
|
||||
#include <lowlevellock.h>
|
||||
#include <pthread.h>
|
||||
#include <pthreadP.h>
|
||||
|
||||
#include <shlib-compat.h>
|
||||
|
||||
|
||||
int
|
||||
__pthread_cond_broadcast (cond)
|
||||
pthread_cond_t *cond;
|
||||
{
|
||||
/* Make sure we are alone. */
|
||||
lll_mutex_lock (cond->__data.__lock);
|
||||
|
||||
/* Are there any waiters to be woken? */
|
||||
if (cond->__data.__total_seq > cond->__data.__wakeup_seq)
|
||||
{
|
||||
/* Yes. Mark them all as woken. */
|
||||
cond->__data.__wakeup_seq = cond->__data.__total_seq;
|
||||
|
||||
/* The futex syscall operates on a 32-bit word. That is fine,
|
||||
we just use the low 32 bits of the sequence counter. */
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
int *futex = ((int *) (&cond->__data.__wakeup_seq));
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
int *futex = ((int *) (&cond->__data.__wakeup_seq)) + 1;
|
||||
#else
|
||||
# error "No valid byte order"
|
||||
#endif
|
||||
|
||||
/* Wake everybody. */
|
||||
lll_futex_wake (futex, INT_MAX);
|
||||
}
|
||||
|
||||
/* We are done. */
|
||||
lll_mutex_unlock (cond->__data.__lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast,
|
||||
GLIBC_2_3_2);
|
63
nptl/sysdeps/pthread/pthread_cond_signal.c
Normal file
63
nptl/sysdeps/pthread/pthread_cond_signal.c
Normal file
@ -0,0 +1,63 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 <endian.h>
|
||||
#include <errno.h>
|
||||
#include <sysdep.h>
|
||||
#include <lowlevellock.h>
|
||||
#include <pthread.h>
|
||||
#include <pthreadP.h>
|
||||
|
||||
#include <shlib-compat.h>
|
||||
|
||||
int
|
||||
__pthread_cond_signal (cond)
|
||||
pthread_cond_t *cond;
|
||||
{
|
||||
/* Make sure we are alone. */
|
||||
lll_mutex_lock(cond->__data.__lock);
|
||||
|
||||
/* Are there any waiters to be woken? */
|
||||
if (cond->__data.__total_seq > cond->__data.__wakeup_seq)
|
||||
{
|
||||
/* Yes. Mark one of them as woken. */
|
||||
++cond->__data.__wakeup_seq;
|
||||
|
||||
/* The futex syscall operates on a 32-bit word. That is fine,
|
||||
we just use the low 32 bits of the sequence counter. */
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
int *futex = ((int *) (&cond->__data.__wakeup_seq));
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
int *futex = ((int *) (&cond->__data.__wakeup_seq)) + 1;
|
||||
#else
|
||||
# error "No valid byte order"
|
||||
#endif
|
||||
|
||||
/* Wake one. */
|
||||
lll_futex_wake (futex, 1);
|
||||
}
|
||||
|
||||
/* We are done. */
|
||||
lll_mutex_unlock (cond->__data.__lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal,
|
||||
GLIBC_2_3_2);
|
153
nptl/sysdeps/pthread/pthread_cond_timedwait.c
Normal file
153
nptl/sysdeps/pthread/pthread_cond_timedwait.c
Normal file
@ -0,0 +1,153 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 <endian.h>
|
||||
#include <errno.h>
|
||||
#include <sysdep.h>
|
||||
#include <lowlevellock.h>
|
||||
#include <pthread.h>
|
||||
#include <pthreadP.h>
|
||||
|
||||
#include <shlib-compat.h>
|
||||
|
||||
|
||||
/* Cleanup handler, defined in pthread_cond_wait.c. */
|
||||
extern void __condvar_cleanup (void *arg)
|
||||
__attribute__ ((visibility ("hidden")));
|
||||
|
||||
|
||||
int
|
||||
__pthread_cond_timedwait (cond, mutex, abstime)
|
||||
pthread_cond_t *cond;
|
||||
pthread_mutex_t *mutex;
|
||||
const struct timespec *abstime;
|
||||
{
|
||||
struct _pthread_cleanup_buffer buffer;
|
||||
int result = 0;
|
||||
|
||||
/* Catch invalid parameters. */
|
||||
if (abstime->tv_nsec >= 1000000000)
|
||||
return EINVAL;
|
||||
|
||||
/* Make sure we are along. */
|
||||
lll_mutex_lock (cond->__data.__lock);
|
||||
|
||||
/* Now we can release the mutex. */
|
||||
__pthread_mutex_unlock_internal (mutex);
|
||||
|
||||
/* We have one new user of the condvar. */
|
||||
++cond->__data.__total_seq;
|
||||
|
||||
/* Before we block we enable cancellation. Therefore we have to
|
||||
install a cancellation handler. */
|
||||
__pthread_cleanup_push (&buffer, __condvar_cleanup, cond);
|
||||
|
||||
/* The current values of the wakeup counter. The "woken" counter
|
||||
must exceed this value. */
|
||||
unsigned long long int val;
|
||||
unsigned long long int seq;
|
||||
val = seq = cond->__data.__wakeup_seq;
|
||||
|
||||
/* The futex syscall operates on a 32-bit word. That is fine, we
|
||||
just use the low 32 bits of the sequence counter. */
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
int *futex = ((int *) (&cond->__data.__wakeup_seq));
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
int *futex = ((int *) (&cond->__data.__wakeup_seq)) + 1;
|
||||
#else
|
||||
# error "No valid byte order"
|
||||
#endif
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* Get the current time. So far we support only one clock. */
|
||||
struct timeval tv;
|
||||
(void) gettimeofday (&tv, NULL);
|
||||
|
||||
/* Convert the absolute timeout value to a relative timeout. */
|
||||
struct timespec rt;
|
||||
rt.tv_sec = abstime->tv_sec - tv.tv_sec;
|
||||
rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
|
||||
if (rt.tv_nsec < 0)
|
||||
{
|
||||
rt.tv_nsec += 1000000000;
|
||||
--rt.tv_sec;
|
||||
}
|
||||
/* Did we already time out? */
|
||||
if (rt.tv_sec < 0)
|
||||
{
|
||||
/* Yep. Adjust the sequence counter. */
|
||||
++cond->__data.__wakeup_seq;
|
||||
|
||||
/* The error value. */
|
||||
result = ETIMEDOUT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Prepare to wait. Release the condvar futex. */
|
||||
lll_mutex_unlock (cond->__data.__lock);
|
||||
|
||||
/* Enable asynchronous cancellation. Required by the standard. */
|
||||
int oldtype = __pthread_enable_asynccancel ();
|
||||
|
||||
/* Wait until woken by signal or broadcast. Note that we
|
||||
truncate the 'val' value to 32 bits. */
|
||||
result = lll_futex_timed_wait (futex, (unsigned int) val, &rt);
|
||||
|
||||
/* Disable asynchronous cancellation. */
|
||||
__pthread_disable_asynccancel (oldtype);
|
||||
|
||||
/* We are going to look at shared data again, so get the lock. */
|
||||
lll_mutex_lock(cond->__data.__lock);
|
||||
|
||||
/* Check whether we are eligible for wakeup. */
|
||||
val = cond->__data.__wakeup_seq;
|
||||
if (cond->__data.__woken_seq >= seq
|
||||
&& cond->__data.__woken_seq < val)
|
||||
break;
|
||||
|
||||
/* Not woken yet. Maybe the time expired? */
|
||||
if (result == -ETIMEDOUT)
|
||||
{
|
||||
/* Yep. Adjust the counters. */
|
||||
++cond->__data.__wakeup_seq;
|
||||
|
||||
/* The error value. */
|
||||
result = ETIMEDOUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Another thread woken up. */
|
||||
++cond->__data.__woken_seq;
|
||||
|
||||
/* We are done with the condvar. */
|
||||
lll_mutex_unlock (cond->__data.__lock);
|
||||
|
||||
/* The cancellation handling is back to normal, remove the handler. */
|
||||
__pthread_cleanup_pop (&buffer, 0);
|
||||
|
||||
/* Get the mutex before returning. */
|
||||
__pthread_mutex_lock_internal (mutex);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
|
||||
GLIBC_2_3_2);
|
126
nptl/sysdeps/pthread/pthread_cond_wait.c
Normal file
126
nptl/sysdeps/pthread/pthread_cond_wait.c
Normal file
@ -0,0 +1,126 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 <endian.h>
|
||||
#include <errno.h>
|
||||
#include <sysdep.h>
|
||||
#include <lowlevellock.h>
|
||||
#include <pthread.h>
|
||||
#include <pthreadP.h>
|
||||
|
||||
#include <shlib-compat.h>
|
||||
|
||||
|
||||
void
|
||||
__attribute__ ((visibility ("hidden")))
|
||||
__condvar_cleanup (void *arg)
|
||||
{
|
||||
pthread_cond_t *cond = (pthread_cond_t *) arg;
|
||||
|
||||
/* We are going to modify shared data. */
|
||||
lll_mutex_lock (cond->__data.__lock);
|
||||
|
||||
/* This thread is not waiting anymore. Adjust the sequence counters
|
||||
appropriately. */
|
||||
++cond->__data.__wakeup_seq;
|
||||
++cond->__data.__woken_seq;
|
||||
|
||||
/* We are done. */
|
||||
lll_mutex_unlock (cond->__data.__lock);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
__pthread_cond_wait (cond, mutex)
|
||||
pthread_cond_t *cond;
|
||||
pthread_mutex_t *mutex;
|
||||
{
|
||||
struct _pthread_cleanup_buffer buffer;
|
||||
|
||||
/* Make sure we are along. */
|
||||
lll_mutex_lock (cond->__data.__lock);
|
||||
|
||||
/* Now we can release the mutex. */
|
||||
__pthread_mutex_unlock_internal (mutex);
|
||||
|
||||
/* We have one new user of the condvar. */
|
||||
++cond->__data.__total_seq;
|
||||
|
||||
/* Before we block we enable cancellation. Therefore we have to
|
||||
install a cancellation handler. */
|
||||
__pthread_cleanup_push (&buffer, __condvar_cleanup, cond);
|
||||
|
||||
/* The current values of the wakeup counter. The "woken" counter
|
||||
must exceed this value. */
|
||||
unsigned long long int val;
|
||||
unsigned long long int seq;
|
||||
val = seq = cond->__data.__wakeup_seq;
|
||||
|
||||
/* The futex syscall operates on a 32-bit word. That is fine, we
|
||||
just use the low 32 bits of the sequence counter. */
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
int *futex = ((int *) (&cond->__data.__wakeup_seq));
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
int *futex = ((int *) (&cond->__data.__wakeup_seq)) + 1;
|
||||
#else
|
||||
# error "No valid byte order"
|
||||
#endif
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* Prepare to wait. Release the condvar futex. */
|
||||
lll_mutex_unlock (cond->__data.__lock);
|
||||
|
||||
/* Enable asynchronous cancellation. Required by the standard. */
|
||||
int oldtype = __pthread_enable_asynccancel ();
|
||||
|
||||
/* Wait until woken by signal or broadcast. Note that we
|
||||
truncate the 'val' value to 32 bits. */
|
||||
lll_futex_wait (futex, (unsigned int) val);
|
||||
|
||||
/* Disable asynchronous cancellation. */
|
||||
__pthread_disable_asynccancel (oldtype);
|
||||
|
||||
/* We are going to look at shared data again, so get the lock. */
|
||||
lll_mutex_lock(cond->__data.__lock);
|
||||
|
||||
/* Check whether we are eligible for wakeup. */
|
||||
val = cond->__data.__wakeup_seq;
|
||||
if (cond->__data.__woken_seq >= seq
|
||||
&& cond->__data.__woken_seq < val)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Another thread woken up. */
|
||||
++cond->__data.__woken_seq;
|
||||
|
||||
/* We are done with the condvar. */
|
||||
lll_mutex_unlock (cond->__data.__lock);
|
||||
|
||||
/* The cancellation handling is back to normal, remove the handler. */
|
||||
__pthread_cleanup_pop (&buffer, 0);
|
||||
|
||||
/* Get the mutex before returning. */
|
||||
__pthread_mutex_lock_internal (mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
|
||||
GLIBC_2_3_2);
|
96
nptl/sysdeps/pthread/pthread_rwlock_rdlock.c
Normal file
96
nptl/sysdeps/pthread/pthread_rwlock_rdlock.c
Normal file
@ -0,0 +1,96 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 <errno.h>
|
||||
#include <sysdep.h>
|
||||
#include <lowlevellock.h>
|
||||
#include <pthread.h>
|
||||
#include <pthreadP.h>
|
||||
|
||||
|
||||
/* Acquire read lock for RWLOCK. */
|
||||
int
|
||||
__pthread_rwlock_rdlock (rwlock)
|
||||
pthread_rwlock_t *rwlock;
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
/* Make sure we are along. */
|
||||
lll_mutex_lock (rwlock->__data.__lock);
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* Get the rwlock if there is no writer... */
|
||||
if (rwlock->__data.__writer == 0
|
||||
/* ...and if either no writer is waiting or we prefer readers. */
|
||||
&& (!rwlock->__data.__nr_writers_queued
|
||||
|| rwlock->__data.__flags == 0))
|
||||
{
|
||||
/* Increment the reader counter. Avoid overflow. */
|
||||
if (__builtin_expect (++rwlock->__data.__nr_readers == 0, 0))
|
||||
{
|
||||
/* Overflow on number of readers. */
|
||||
--rwlock->__data.__nr_readers;
|
||||
result = EAGAIN;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Make sure we are not holding the rwlock as a writer. This is
|
||||
a deadlock situation we recognize and report. */
|
||||
if (rwlock->__data.__writer != 0
|
||||
&& __builtin_expect (rwlock->__data.__writer
|
||||
== (pthread_t) THREAD_SELF, 0))
|
||||
{
|
||||
result = EDEADLK;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Remember that we are a reader. */
|
||||
if (__builtin_expect (++rwlock->__data.__nr_readers_queued == 0, 0))
|
||||
{
|
||||
/* Overflow on number of queued readers. */
|
||||
--rwlock->__data.__nr_readers_queued;
|
||||
result = EAGAIN;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Free the lock. */
|
||||
lll_mutex_unlock (rwlock->__data.__lock);
|
||||
|
||||
/* Wait for the writer to finish. */
|
||||
lll_futex_wait (&rwlock->__data.__readers_wakeup, 0);
|
||||
|
||||
/* Get the lock. */
|
||||
lll_mutex_lock (rwlock->__data.__lock);
|
||||
|
||||
/* To start over again, remove the thread from the reader list. */
|
||||
if (--rwlock->__data.__nr_readers_queued == 0)
|
||||
rwlock->__data.__readers_wakeup = 0;
|
||||
}
|
||||
|
||||
/* We are done, free the lock. */
|
||||
lll_mutex_unlock (rwlock->__data.__lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
weak_alias (__pthread_rwlock_rdlock, pthread_rwlock_rdlock)
|
||||
strong_alias (__pthread_rwlock_rdlock, __pthread_rwlock_rdlock_internal)
|
134
nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c
Normal file
134
nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c
Normal file
@ -0,0 +1,134 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 <errno.h>
|
||||
#include <sysdep.h>
|
||||
#include <lowlevellock.h>
|
||||
#include <pthread.h>
|
||||
#include <pthreadP.h>
|
||||
|
||||
|
||||
/* Try to acquire read lock for RWLOCK or return after specfied time. */
|
||||
int
|
||||
pthread_rwlock_timedrdlock (rwlock, abstime)
|
||||
pthread_rwlock_t *rwlock;
|
||||
const struct timespec *abstime;
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
/* Make sure we are along. */
|
||||
lll_mutex_lock(rwlock->__data.__lock);
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* Get the rwlock if there is no writer... */
|
||||
if (rwlock->__data.__writer == 0
|
||||
/* ...and if either no writer is waiting or we prefer readers. */
|
||||
&& (!rwlock->__data.__nr_writers_queued
|
||||
|| rwlock->__data.__flags == 0))
|
||||
{
|
||||
/* Increment the reader counter. Avoid overflow. */
|
||||
if (++rwlock->__data.__nr_readers == 0)
|
||||
{
|
||||
/* Overflow on number of readers. */
|
||||
--rwlock->__data.__nr_readers;
|
||||
result = EAGAIN;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Make sure we are not holding the rwlock as a writer. This is
|
||||
a deadlock situation we recognize and report. */
|
||||
if (rwlock->__data.__writer != 0
|
||||
&& __builtin_expect (rwlock->__data.__writer
|
||||
== (pthread_t) THREAD_SELF, 0))
|
||||
{
|
||||
result = EDEADLK;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Make sure the passed in timeout value is valid. Ideally this
|
||||
test would be executed once. But since it must not be
|
||||
performed if we would not block at all simply moving the test
|
||||
to the front is no option. Replicating all the code is
|
||||
costly while this test is not. */
|
||||
if (__builtin_expect (abstime->tv_nsec >= 1000000000, 0))
|
||||
{
|
||||
result = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get the current time. So far we support only one clock. */
|
||||
struct timeval tv;
|
||||
(void) gettimeofday (&tv, NULL);
|
||||
|
||||
/* Convert the absolute timeout value to a relative timeout. */
|
||||
struct timespec rt;
|
||||
rt.tv_sec = abstime->tv_sec - tv.tv_sec;
|
||||
rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
|
||||
if (rt.tv_nsec < 0)
|
||||
{
|
||||
rt.tv_nsec += 1000000000;
|
||||
--rt.tv_sec;
|
||||
}
|
||||
/* Did we already time out? */
|
||||
if (rt.tv_sec < 0)
|
||||
{
|
||||
/* Yep, return with an appropriate error. */
|
||||
result = ETIMEDOUT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Remember that we are a reader. */
|
||||
if (++rwlock->__data.__nr_readers_queued == 0)
|
||||
{
|
||||
/* Overflow on number of queued readers. */
|
||||
--rwlock->__data.__nr_readers_queued;
|
||||
result = EAGAIN;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Free the lock. */
|
||||
lll_mutex_unlock (rwlock->__data.__lock);
|
||||
|
||||
/* Wait for the writer to finish. */
|
||||
result = lll_futex_timed_wait (&rwlock->__data.__readers_wakeup, 0, &rt);
|
||||
|
||||
/* Get the lock. */
|
||||
lll_mutex_lock (rwlock->__data.__lock);
|
||||
|
||||
/* To start over again, remove the thread from the reader list. */
|
||||
if (--rwlock->__data.__nr_readers_queued == 0)
|
||||
rwlock->__data.__readers_wakeup = 0;
|
||||
|
||||
/* Did the futex call time out? */
|
||||
if (result == -ETIMEDOUT)
|
||||
{
|
||||
/* Yep, report it. */
|
||||
result = ETIMEDOUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* We are done, free the lock. */
|
||||
lll_mutex_unlock (rwlock->__data.__lock);
|
||||
|
||||
return result;
|
||||
}
|
123
nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c
Normal file
123
nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c
Normal file
@ -0,0 +1,123 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 <errno.h>
|
||||
#include <sysdep.h>
|
||||
#include <lowlevellock.h>
|
||||
#include <pthread.h>
|
||||
#include <pthreadP.h>
|
||||
|
||||
|
||||
/* Try to acquire write lock for RWLOCK or return after specfied time. */
|
||||
int
|
||||
pthread_rwlock_timedwrlock (rwlock, abstime)
|
||||
pthread_rwlock_t *rwlock;
|
||||
const struct timespec *abstime;
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
/* Make sure we are along. */
|
||||
lll_mutex_lock (rwlock->__data.__lock);
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* Get the rwlock if there is no writer and no reader. */
|
||||
if (rwlock->__data.__writer == 0 && rwlock->__data.__nr_readers == 0)
|
||||
{
|
||||
/* Mark self as writer. */
|
||||
rwlock->__data.__writer = (pthread_t) THREAD_SELF;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Make sure we are not holding the rwlock as a writer. This is
|
||||
a deadlock situation we recognize and report. */
|
||||
if (rwlock->__data.__writer != 0
|
||||
&& __builtin_expect (rwlock->__data.__writer
|
||||
== (pthread_t) THREAD_SELF, 0))
|
||||
{
|
||||
result = EDEADLK;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Make sure the passed in timeout value is valid. Ideally this
|
||||
test would be executed once. But since it must not be
|
||||
performed if we would not block at all simply moving the test
|
||||
to the front is no option. Replicating all the code is
|
||||
costly while this test is not. */
|
||||
if (abstime->tv_nsec >= 1000000000)
|
||||
{
|
||||
result = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get the current time. So far we support only one clock. */
|
||||
struct timeval tv;
|
||||
(void) gettimeofday (&tv, NULL);
|
||||
|
||||
/* Convert the absolute timeout value to a relative timeout. */
|
||||
struct timespec rt;
|
||||
rt.tv_sec = abstime->tv_sec - tv.tv_sec;
|
||||
rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
|
||||
if (rt.tv_nsec < 0)
|
||||
{
|
||||
rt.tv_nsec += 1000000000;
|
||||
--rt.tv_sec;
|
||||
}
|
||||
/* Did we already time out? */
|
||||
if (rt.tv_sec < 0)
|
||||
{
|
||||
result = ETIMEDOUT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Remember that we are a writer. */
|
||||
if (++rwlock->__data.__nr_writers_queued == 0)
|
||||
{
|
||||
/* Overflow on number of queued writers. */
|
||||
--rwlock->__data.__nr_writers_queued;
|
||||
result = EAGAIN;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Free the lock. */
|
||||
lll_mutex_unlock (rwlock->__data.__lock);
|
||||
|
||||
/* Wait for the writer or reader(s) to finish. */
|
||||
result = lll_futex_timed_wait (&rwlock->__data.__writer_wakeup, 0, &rt);
|
||||
|
||||
/* Get the lock. */
|
||||
lll_mutex_lock (rwlock->__data.__lock);
|
||||
|
||||
/* To start over again, remove the thread from the writer list. */
|
||||
--rwlock->__data.__nr_writers_queued;
|
||||
rwlock->__data.__writer_wakeup = 0;
|
||||
|
||||
/* Did the futex call time out? */
|
||||
if (result == -ETIMEDOUT)
|
||||
{
|
||||
result = ETIMEDOUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* We are done, free the lock. */
|
||||
lll_mutex_unlock (rwlock->__data.__lock);
|
||||
|
||||
return result;
|
||||
}
|
52
nptl/sysdeps/pthread/pthread_rwlock_unlock.c
Normal file
52
nptl/sysdeps/pthread/pthread_rwlock_unlock.c
Normal file
@ -0,0 +1,52 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 <errno.h>
|
||||
#include <sysdep.h>
|
||||
#include <lowlevellock.h>
|
||||
#include <pthread.h>
|
||||
#include <pthreadP.h>
|
||||
|
||||
/* Unlock RWLOCK. */
|
||||
int __pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
|
||||
{
|
||||
lll_mutex_lock(rwlock->__data.__lock);
|
||||
if (rwlock->__data.__writer)
|
||||
rwlock->__data.__writer = 0;
|
||||
else
|
||||
rwlock->__data.__nr_readers--;
|
||||
if (!rwlock->__data.__nr_readers)
|
||||
{
|
||||
if (rwlock->__data.__nr_writers_queued)
|
||||
{
|
||||
rwlock->__data.__writer_wakeup = 1;
|
||||
lll_futex_wake(&rwlock->__data.__writer_wakeup, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
rwlock->__data.__readers_wakeup = 1;
|
||||
lll_futex_wake(&rwlock->__data.__readers_wakeup, INT_MAX);
|
||||
}
|
||||
}
|
||||
lll_mutex_unlock(rwlock->__data.__lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
weak_alias (__pthread_rwlock_unlock, pthread_rwlock_unlock)
|
||||
strong_alias (__pthread_rwlock_unlock, __pthread_rwlock_unlock_internal)
|
87
nptl/sysdeps/pthread/pthread_rwlock_wrlock.c
Normal file
87
nptl/sysdeps/pthread/pthread_rwlock_wrlock.c
Normal file
@ -0,0 +1,87 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 <errno.h>
|
||||
#include <sysdep.h>
|
||||
#include <lowlevellock.h>
|
||||
#include <pthread.h>
|
||||
#include <pthreadP.h>
|
||||
|
||||
|
||||
/* Acquire write lock for RWLOCK. */
|
||||
int
|
||||
__pthread_rwlock_wrlock (rwlock)
|
||||
pthread_rwlock_t *rwlock;
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
/* Make sure we are along. */
|
||||
lll_mutex_lock (rwlock->__data.__lock);
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* Get the rwlock if there is no writer and no reader. */
|
||||
if (rwlock->__data.__writer == 0 && rwlock->__data.__nr_readers == 0)
|
||||
{
|
||||
/* Mark self as writer. */
|
||||
rwlock->__data.__writer = (pthread_t) THREAD_SELF;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Make sure we are not holding the rwlock as a writer. This is
|
||||
a deadlock situation we recognize and report. */
|
||||
if (rwlock->__data.__writer != 0
|
||||
&& __builtin_expect (rwlock->__data.__writer
|
||||
== (pthread_t) THREAD_SELF, 0))
|
||||
{
|
||||
result = EDEADLK;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Remember that we are a writer. */
|
||||
if (++rwlock->__data.__nr_writers_queued == 0)
|
||||
{
|
||||
/* Overflow on number of queued writers. */
|
||||
--rwlock->__data.__nr_writers_queued;
|
||||
result = EAGAIN;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Free the lock. */
|
||||
lll_mutex_unlock (rwlock->__data.__lock);
|
||||
|
||||
/* Wait for the writer or reader(s) to finish. */
|
||||
lll_futex_wait (&rwlock->__data.__writer_wakeup, 0);
|
||||
|
||||
/* Get the lock. */
|
||||
lll_mutex_lock (rwlock->__data.__lock);
|
||||
|
||||
/* To start over again, remove the thread from the writer list. */
|
||||
--rwlock->__data.__nr_writers_queued;
|
||||
rwlock->__data.__writer_wakeup = 0;
|
||||
}
|
||||
|
||||
/* We are done, free the lock. */
|
||||
lll_mutex_unlock (rwlock->__data.__lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
weak_alias (__pthread_rwlock_wrlock, pthread_rwlock_wrlock)
|
||||
strong_alias (__pthread_rwlock_wrlock, __pthread_rwlock_wrlock_internal)
|
25
nptl/sysdeps/s390/Makefile
Normal file
25
nptl/sysdeps/s390/Makefile
Normal file
@ -0,0 +1,25 @@
|
||||
# Copyright (C) 2003 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, write to the Free
|
||||
# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
# 02111-1307 USA.
|
||||
|
||||
ifeq ($(subdir),csu)
|
||||
gen-as-const-headers += tcb-offsets.sym
|
||||
endif
|
||||
|
||||
ifeq ($(subdir),nptl)
|
||||
libpthread-routines += ptw-sysdep
|
||||
endif
|
78
nptl/sysdeps/s390/bits/atomic.h
Normal file
78
nptl/sysdeps/s390/bits/atomic.h
Normal file
@ -0,0 +1,78 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 <stdint.h>
|
||||
|
||||
typedef int8_t atomic8_t;
|
||||
typedef uint8_t uatomic8_t;
|
||||
typedef int_fast8_t atomic_fast8_t;
|
||||
typedef uint_fast8_t uatomic_fast8_t;
|
||||
|
||||
typedef int16_t atomic16_t;
|
||||
typedef uint16_t uatomic16_t;
|
||||
typedef int_fast16_t atomic_fast16_t;
|
||||
typedef uint_fast16_t uatomic_fast16_t;
|
||||
|
||||
typedef int32_t atomic32_t;
|
||||
typedef uint32_t uatomic32_t;
|
||||
typedef int_fast32_t atomic_fast32_t;
|
||||
typedef uint_fast32_t uatomic_fast32_t;
|
||||
|
||||
typedef int64_t atomic64_t;
|
||||
typedef uint64_t uatomic64_t;
|
||||
typedef int_fast64_t atomic_fast64_t;
|
||||
typedef uint_fast64_t uatomic_fast64_t;
|
||||
|
||||
typedef intptr_t atomicptr_t;
|
||||
typedef uintptr_t uatomicptr_t;
|
||||
typedef intmax_t atomic_max_t;
|
||||
typedef uintmax_t uatomic_max_t;
|
||||
|
||||
|
||||
#define __arch_compare_and_exchange_8_acq(mem, newval, oldval) \
|
||||
(abort (), 0)
|
||||
|
||||
#define __arch_compare_and_exchange_16_acq(mem, newval, oldval) \
|
||||
(abort (), 0)
|
||||
|
||||
#define __arch_compare_and_exchange_32_acq(mem, newval, oldval) \
|
||||
({ unsigned int *__mem = (unsigned int *) (mem); \
|
||||
unsigned int __old = (unsigned int) (oldval); \
|
||||
unsigned int __cmp = __old; \
|
||||
__asm __volatile ("cs %0,%2,%1" \
|
||||
: "+d" (__old), "=Q" (*__mem) \
|
||||
: "d" (newval), "m" (*__mem) : "cc" ); \
|
||||
__cmp != __old; })
|
||||
|
||||
#ifdef __s390x__
|
||||
# define __arch_compare_and_exchange_64_acq(mem, newval, oldval) \
|
||||
({ unsigned long int *__mem = (unsigned long int *) (mem); \
|
||||
unsigned long int __old = (unsigned long int) (oldval); \
|
||||
unsigned long int __cmp = __old; \
|
||||
__asm __volatile ("csg %0,%2,%1" \
|
||||
: "+d" (__old), "=Q" (*__mem) \
|
||||
: "d" (newval), "m" (*__mem) : "cc" ); \
|
||||
__cmp != __old; })
|
||||
#else
|
||||
/* For 31 bit we do not really need 64-bit compare-and-exchange. We can
|
||||
implement them by use of the csd instruction. The straightforward
|
||||
implementation causes warnings so we skip the definition for now. */
|
||||
# define __arch_compare_and_exchange_64_acq(mem, newval, oldval) \
|
||||
(abort (), 0)
|
||||
#endif
|
20
nptl/sysdeps/s390/pthread_spin_init.c
Normal file
20
nptl/sysdeps/s390/pthread_spin_init.c
Normal file
@ -0,0 +1,20 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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. */
|
||||
|
||||
/* Not needed. pthread_spin_init is an alias for pthread_spin_unlock. */
|
34
nptl/sysdeps/s390/pthread_spin_lock.c
Normal file
34
nptl/sysdeps/s390/pthread_spin_lock.c
Normal file
@ -0,0 +1,34 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 "pthreadP.h"
|
||||
|
||||
int
|
||||
pthread_spin_lock (lock)
|
||||
pthread_spinlock_t *lock;
|
||||
{
|
||||
unsigned long int oldval;
|
||||
|
||||
__asm __volatile ("0: lhi %0,0\n"
|
||||
" cs %0,%2,%1\n"
|
||||
" jl 0b"
|
||||
: "=d" (oldval), "=Q" (*lock)
|
||||
: "d" (1), "m" (*lock) : "cc" );
|
||||
return 0;
|
||||
}
|
34
nptl/sysdeps/s390/pthread_spin_trylock.c
Normal file
34
nptl/sysdeps/s390/pthread_spin_trylock.c
Normal file
@ -0,0 +1,34 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 <errno.h>
|
||||
#include "pthreadP.h"
|
||||
|
||||
int
|
||||
pthread_spin_trylock (lock)
|
||||
pthread_spinlock_t *lock;
|
||||
{
|
||||
unsigned long int old;
|
||||
|
||||
__asm __volatile ("cs %0,%3,%1"
|
||||
: "=d" (old), "=Q" (*lock)
|
||||
: "0" (0), "d" (1), "m" (*lock) : "cc" );
|
||||
|
||||
return old != 0 ? EBUSY : 0;
|
||||
}
|
33
nptl/sysdeps/s390/pthread_spin_unlock.c
Normal file
33
nptl/sysdeps/s390/pthread_spin_unlock.c
Normal file
@ -0,0 +1,33 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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. */
|
||||
|
||||
/* Ugly hack to avoid the declaration of pthread_spin_init. */
|
||||
#define pthread_spin_init pthread_spin_init_XXX
|
||||
#include "pthreadP.h"
|
||||
#undef pthread_spin_init
|
||||
|
||||
int
|
||||
pthread_spin_unlock (pthread_spinlock_t *lock)
|
||||
{
|
||||
__asm __volatile (" xc %O0(4,%R0),%0\n"
|
||||
" bcr 15,0"
|
||||
: "=Q" (*lock) : "m" (*lock) : "cc" );
|
||||
return 0;
|
||||
}
|
||||
strong_alias (pthread_spin_unlock, pthread_spin_init)
|
44
nptl/sysdeps/s390/pthreaddef.h
Normal file
44
nptl/sysdeps/s390/pthreaddef.h
Normal file
@ -0,0 +1,44 @@
|
||||
/* Copyright (C) 2003 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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
/* Default stack size. */
|
||||
#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024)
|
||||
|
||||
/* Required stack pointer alignment at beginning. SSE requires 16
|
||||
bytes. */
|
||||
#define STACK_ALIGN 16
|
||||
|
||||
/* Minimal stack size after allocating thread descriptor and guard size. */
|
||||
#define MINIMAL_REST_STACK 2048
|
||||
|
||||
/* Alignment requirement for TCB. */
|
||||
#define TCB_ALIGNMENT 16
|
||||
|
||||
/* The signal used for asynchronous cancelation. */
|
||||
#define SIGCANCEL __SIGRTMIN
|
||||
|
||||
|
||||
/* Location of current stack frame. */
|
||||
#define CURRENT_STACK_FRAME __builtin_frame_address (0)
|
||||
|
||||
|
||||
/* XXX Until we have a better place keep the definitions here. */
|
||||
|
||||
/* While there is no such syscall. */
|
||||
#define __exit_thread_inline(val) \
|
||||
INLINE_SYSCALL (exit, 0)
|
4
nptl/sysdeps/s390/tcb-offsets.sym
Normal file
4
nptl/sysdeps/s390/tcb-offsets.sym
Normal file
@ -0,0 +1,4 @@
|
||||
#include <sysdep.h>
|
||||
#include <tls.h>
|
||||
|
||||
MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads)
|
47
nptl/sysdeps/s390/td_ta_map_lwp2thr.c
Normal file
47
nptl/sysdeps/s390/td_ta_map_lwp2thr.c
Normal file
@ -0,0 +1,47 @@
|
||||
/* Which thread is running on an LWP? i386 version.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 "thread_dbP.h"
|
||||
#include <tls.h>
|
||||
|
||||
|
||||
td_err_e
|
||||
td_ta_map_lwp2thr (const td_thragent_t *ta, lwpid_t lwpid, td_thrhandle_t *th)
|
||||
{
|
||||
LOG ("td_ta_map_lwp2thr");
|
||||
|
||||
/* Test whether the TA parameter is ok. */
|
||||
if (! ta_ok (ta))
|
||||
return TD_BADTA;
|
||||
|
||||
prgregset_t regs;
|
||||
if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK)
|
||||
return TD_ERR;
|
||||
|
||||
/* Get the thread area for the addressed thread. */
|
||||
if (ps_get_thread_area (ta->ph, lwpid, regs[18] >> 3, &th->th_unique)
|
||||
!= PS_OK)
|
||||
return TD_ERR; /* XXX Other error value? */
|
||||
|
||||
/* Found it. Now complete the `td_thrhandle_t' object. */
|
||||
th->th_ta_p = (td_thragent_t *) ta;
|
||||
|
||||
return TD_OK;
|
||||
}
|
149
nptl/sysdeps/s390/tls.h
Normal file
149
nptl/sysdeps/s390/tls.h
Normal file
@ -0,0 +1,149 @@
|
||||
/* Definition for thread-local data handling. nptl/s390 version.
|
||||
Copyright (C) 2003 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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#ifndef _TLS_H
|
||||
#define _TLS_H 1
|
||||
|
||||
#include <dl-sysdep.h>
|
||||
#ifndef __ASSEMBLER__
|
||||
# include <stddef.h>
|
||||
# include <stdint.h>
|
||||
# include <stdlib.h>
|
||||
# include <list.h>
|
||||
|
||||
|
||||
/* Type for the dtv. */
|
||||
typedef union dtv
|
||||
{
|
||||
size_t counter;
|
||||
void *pointer;
|
||||
} dtv_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *tcb; /* Pointer to the TCB. Not necessary the
|
||||
thread descriptor used by libpthread. */
|
||||
dtv_t *dtv;
|
||||
void *self; /* Pointer to the thread descriptor. */
|
||||
int multiple_threads;
|
||||
#ifdef NEED_DL_SYSINFO
|
||||
uintptr_t sysinfo;
|
||||
#endif
|
||||
list_t list;
|
||||
} tcbhead_t;
|
||||
|
||||
#else /* __ASSEMBLER__ */
|
||||
# include <tcb-offsets.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* We require TLS support in the tools. */
|
||||
#ifndef HAVE_TLS_SUPPORT
|
||||
# error "TLS support is required."
|
||||
#endif
|
||||
|
||||
/* Signal that TLS support is available. */
|
||||
#define USE_TLS 1
|
||||
|
||||
/* Alignment requirement for the stack. For IA-32 this is governed by
|
||||
the SSE memory functions. */
|
||||
#define STACK_ALIGN 16
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
/* Get system call information. */
|
||||
# include <sysdep.h>
|
||||
|
||||
/* Get the thread descriptor definition. */
|
||||
# include <nptl/descr.h>
|
||||
|
||||
/* This is the size of the initial TCB. */
|
||||
# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
|
||||
|
||||
/* Alignment requirements for the initial TCB. */
|
||||
# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
|
||||
|
||||
/* This is the size of the TCB. */
|
||||
# define TLS_TCB_SIZE sizeof (struct pthread)
|
||||
|
||||
/* Alignment requirements for the TCB. */
|
||||
# define TLS_TCB_ALIGN __alignof__ (struct pthread)
|
||||
|
||||
/* The TCB can have any size and the memory following the address the
|
||||
thread pointer points to is unspecified. Allocate the TCB there. */
|
||||
# define TLS_TCB_AT_TP 1
|
||||
|
||||
|
||||
/* Install the dtv pointer. The pointer passed is to the element with
|
||||
index -1 which contain the length. */
|
||||
# define INSTALL_DTV(descr, dtvp) \
|
||||
((tcbhead_t *) (descr))->dtv = (dtvp) + 1
|
||||
|
||||
/* Install new dtv for current thread. */
|
||||
# define INSTALL_NEW_DTV(dtv) \
|
||||
(((tcbhead_t *) __builtin_thread_pointer ())->dtv = (dtv))
|
||||
|
||||
/* Return dtv of given thread descriptor. */
|
||||
# define GET_DTV(descr) \
|
||||
(((tcbhead_t *) (descr))->dtv)
|
||||
|
||||
#if defined NEED_DL_SYSINFO && defined SHARED
|
||||
# define INIT_SYSINFO \
|
||||
_head->sysinfo = GL(dl_sysinfo)
|
||||
#else
|
||||
# define INIT_SYSINFO
|
||||
#endif
|
||||
|
||||
/* Code to initially initialize the thread pointer. This might need
|
||||
special attention since 'errno' is not yet available and if the
|
||||
operation can cause a failure 'errno' must not be touched. */
|
||||
# define TLS_INIT_TP(thrdescr, secondcall) \
|
||||
({ void *_thrdescr = (thrdescr); \
|
||||
tcbhead_t *_head = _thrdescr; \
|
||||
\
|
||||
_head->tcb = _thrdescr; \
|
||||
/* For now the thread descriptor is at the same address. */ \
|
||||
_head->self = _thrdescr; \
|
||||
/* New syscall handling support. */ \
|
||||
INIT_SYSINFO; \
|
||||
\
|
||||
__builtin_set_thread_pointer (_thrdescr); \
|
||||
NULL; \
|
||||
})
|
||||
|
||||
/* Return the address of the dtv for the current thread. */
|
||||
# define THREAD_DTV() \
|
||||
(((tcbhead_t *) __builtin_thread_pointer ())->dtv)
|
||||
|
||||
/* Return the thread descriptor for the current thread. */
|
||||
# define THREAD_SELF ((struct pthread *) __builtin_thread_pointer ())
|
||||
|
||||
/* Access to data in the thread descriptor is easy. */
|
||||
#define THREAD_GETMEM(descr, member) \
|
||||
THREAD_SELF->member
|
||||
#define THREAD_GETMEM_NC(descr, member, idx) \
|
||||
THREAD_SELF->member[idx]
|
||||
#define THREAD_SETMEM(descr, member, value) \
|
||||
THREAD_SELF->member = (value)
|
||||
#define THREAD_SETMEM_NC(descr, member, idx, value) \
|
||||
THREAD_SELF->member[idx] = (value)
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
#endif /* tls.h */
|
183
nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h
Normal file
183
nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h
Normal file
@ -0,0 +1,183 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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. */
|
||||
|
||||
#ifndef _BITS_PTHREADTYPES_H
|
||||
#define _BITS_PTHREADTYPES_H 1
|
||||
|
||||
#include <bits/wordsize.h>
|
||||
|
||||
#if __WORDSIZE == 64
|
||||
# define __SIZEOF_PTHREAD_ATTR_T 56
|
||||
# define __SIZEOF_PTHREAD_MUTEX_T 40
|
||||
# define __SIZEOF_PTHREAD_MUTEXATTR_T 4
|
||||
# define __SIZEOF_PTHREAD_COND_T 48
|
||||
# define __SIZEOF_PTHREAD_CONDATTR_T 4
|
||||
# define __SIZEOF_PTHREAD_RWLOCK_T 56
|
||||
# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
|
||||
# define __SIZEOF_PTHREAD_BARRIER_T 32
|
||||
# define __SIZEOF_PTHREAD_BARRIERATTR_T 4
|
||||
#else
|
||||
# define __SIZEOF_PTHREAD_ATTR_T 36
|
||||
# define __SIZEOF_PTHREAD_MUTEX_T 24
|
||||
# define __SIZEOF_PTHREAD_MUTEXATTR_T 4
|
||||
# define __SIZEOF_PTHREAD_COND_T 48
|
||||
# define __SIZEOF_PTHREAD_CONDATTR_T 4
|
||||
# define __SIZEOF_PTHREAD_RWLOCK_T 32
|
||||
# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
|
||||
# define __SIZEOF_PTHREAD_BARRIER_T 20
|
||||
# define __SIZEOF_PTHREAD_BARRIERATTR_T 4
|
||||
#endif
|
||||
|
||||
|
||||
/* Thread identifiers. The structure of the attribute type is not
|
||||
exposed on purpose. */
|
||||
typedef struct __opaque_pthread *pthread_t;
|
||||
|
||||
|
||||
typedef union
|
||||
{
|
||||
char __size[__SIZEOF_PTHREAD_ATTR_T];
|
||||
long int __align;
|
||||
} pthread_attr_t;
|
||||
|
||||
|
||||
/* Data structures for mutex handling. The structure of the attribute
|
||||
type is not exposed on purpose. */
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
int __lock;
|
||||
unsigned int __count;
|
||||
struct pthread *__owner;
|
||||
/* KIND must stay at this position in the structure to maintain
|
||||
binary compatibility. */
|
||||
int __kind;
|
||||
} __data;
|
||||
char __size[__SIZEOF_PTHREAD_MUTEX_T];
|
||||
long int __align;
|
||||
} pthread_mutex_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
|
||||
long int __align;
|
||||
} pthread_mutexattr_t;
|
||||
|
||||
|
||||
/* Data structure for conditional variable handling. The structure of
|
||||
the attribute type is not exposed on purpose. */
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
int __lock;
|
||||
unsigned long long int __total_seq;
|
||||
unsigned long long int __wakeup_seq;
|
||||
unsigned long long int __woken_seq;
|
||||
} __data;
|
||||
char __size[__SIZEOF_PTHREAD_COND_T];
|
||||
long int __align;
|
||||
} pthread_cond_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
char __size[__SIZEOF_PTHREAD_CONDATTR_T];
|
||||
long int __align;
|
||||
} pthread_condattr_t;
|
||||
|
||||
|
||||
/* Keys for thread-specific data */
|
||||
typedef unsigned int pthread_key_t;
|
||||
|
||||
|
||||
/* Once-only execution */
|
||||
typedef int pthread_once_t;
|
||||
|
||||
|
||||
#ifdef __USE_UNIX98
|
||||
/* Data structure for read-write lock variable handling. The
|
||||
structure of the attribute type is not exposed on purpose. */
|
||||
typedef union
|
||||
{
|
||||
# if __WORDSIZE == 64
|
||||
struct
|
||||
{
|
||||
int __lock;
|
||||
unsigned int __nr_readers;
|
||||
unsigned int __readers_wakeup;
|
||||
unsigned int __writer_wakeup;
|
||||
unsigned int __nr_readers_queued;
|
||||
unsigned int __nr_writers_queued;
|
||||
pthread_t __writer;
|
||||
unsigned long int __pad1;
|
||||
unsigned long int __pad2;
|
||||
/* FLAGS must stay at this position in the structure to maintain
|
||||
binary compatibility. */
|
||||
unsigned int __flags;
|
||||
} __data;
|
||||
# else
|
||||
struct
|
||||
{
|
||||
int __lock;
|
||||
unsigned int __nr_readers;
|
||||
unsigned int __readers_wakeup;
|
||||
unsigned int __writer_wakeup;
|
||||
unsigned int __nr_readers_queued;
|
||||
unsigned int __nr_writers_queued;
|
||||
/* FLAGS must stay at this position in the structure to maintain
|
||||
binary compatibility. */
|
||||
unsigned int __flags;
|
||||
pthread_t __writer;
|
||||
} __data;
|
||||
# endif
|
||||
char __size[__SIZEOF_PTHREAD_RWLOCK_T];
|
||||
long int __align;
|
||||
} pthread_rwlock_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T];
|
||||
long int __align;
|
||||
} pthread_rwlockattr_t;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __USE_XOPEN2K
|
||||
/* POSIX spinlock data type. */
|
||||
typedef volatile int pthread_spinlock_t;
|
||||
|
||||
|
||||
/* POSIX barriers data type. The structure of the type is
|
||||
deliberately not exposed. */
|
||||
typedef union
|
||||
{
|
||||
char __size[__SIZEOF_PTHREAD_BARRIER_T];
|
||||
long int __align;
|
||||
} pthread_barrier_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
char __size[__SIZEOF_PTHREAD_BARRIERATTR_T];
|
||||
int __align;
|
||||
} pthread_barrierattr_t;
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* bits/pthreadtypes.h */
|
43
nptl/sysdeps/unix/sysv/linux/s390/bits/semaphore.h
Normal file
43
nptl/sysdeps/unix/sysv/linux/s390/bits/semaphore.h
Normal file
@ -0,0 +1,43 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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. */
|
||||
|
||||
#ifndef _SEMAPHORE_H
|
||||
# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead."
|
||||
#endif
|
||||
|
||||
#include <bits/wordsize.h>
|
||||
|
||||
#if __WORDSIZE == 64
|
||||
# define __SIZEOF_SEM_T 32
|
||||
#else
|
||||
# define __SIZEOF_SEM_T 16
|
||||
#endif
|
||||
|
||||
/* Value returned if `sem_open' failed. */
|
||||
#define SEM_FAILED ((sem_t *) 0)
|
||||
|
||||
/* Maximum value the semaphore can have. */
|
||||
#define SEM_VALUE_MAX ((int) ((~0u) >> 1))
|
||||
|
||||
|
||||
typedef union
|
||||
{
|
||||
char __size[__SIZEOF_SEM_T];
|
||||
long int __align;
|
||||
} sem_t;
|
24
nptl/sysdeps/unix/sysv/linux/s390/createthread.c
Normal file
24
nptl/sysdeps/unix/sysv/linux/s390/createthread.c
Normal file
@ -0,0 +1,24 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>.
|
||||
|
||||
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. */
|
||||
|
||||
/* Value passed to 'clone' for initialization of the thread register. */
|
||||
#define TLS_VALUE pd
|
||||
|
||||
/* Get the real implementation. */
|
||||
#include <nptl/sysdeps/pthread/createthread.c>
|
37
nptl/sysdeps/unix/sysv/linux/s390/dl-sysdep.h
Normal file
37
nptl/sysdeps/unix/sysv/linux/s390/dl-sysdep.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* System-specific settings for dynamic linker code. s390 version.
|
||||
Copyright (C) 2003 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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#ifndef _DL_SYSDEP_H
|
||||
#define _DL_SYSDEP_H 1
|
||||
|
||||
/* This macro must be defined to either 0 or 1.
|
||||
|
||||
If 1, then an errno global variable hidden in ld.so will work right with
|
||||
all the errno-using libc code compiled for ld.so, and there is never a
|
||||
need to share the errno location with libc. This is appropriate only if
|
||||
all the libc functions that ld.so uses are called without PLT and always
|
||||
get the versions linked into ld.so rather than the libc ones. */
|
||||
|
||||
#ifdef IS_IN_rtld
|
||||
# define RTLD_PRIVATE_ERRNO 1
|
||||
#else
|
||||
# define RTLD_PRIVATE_ERRNO 0
|
||||
#endif
|
||||
|
||||
#endif /* dl-sysdep.h */
|
31
nptl/sysdeps/unix/sysv/linux/s390/fork.c
Normal file
31
nptl/sysdeps/unix/sysv/linux/s390/fork.c
Normal file
@ -0,0 +1,31 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 <sched.h>
|
||||
#include <signal.h>
|
||||
#include <sysdep.h>
|
||||
#include <tls.h>
|
||||
|
||||
|
||||
#define ARCH_FORK() \
|
||||
INLINE_SYSCALL (clone, 5, \
|
||||
0, CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, \
|
||||
NULL, &THREAD_SELF->tid, NULL)
|
||||
|
||||
#include "../fork.c"
|
41
nptl/sysdeps/unix/sysv/linux/s390/jmp-unwind.c
Normal file
41
nptl/sysdeps/unix/sysv/linux/s390/jmp-unwind.c
Normal file
@ -0,0 +1,41 @@
|
||||
/* Clean up stack frames unwound by longjmp. Linux/s390 version.
|
||||
Copyright (C) 2003 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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <stddef.h>
|
||||
#include <pthread-functions.h>
|
||||
|
||||
extern void __pthread_cleanup_upto (jmp_buf env, char *targetframe);
|
||||
#pragma weak __pthread_cleanup_upto
|
||||
|
||||
|
||||
void
|
||||
_longjmp_unwind (jmp_buf env, int val)
|
||||
{
|
||||
#ifdef SHARED
|
||||
# define fptr __libc_pthread_functions.ptr___pthread_cleanup_upto
|
||||
#else
|
||||
# define fptr __pthread_cleanup_upto
|
||||
#endif
|
||||
|
||||
unsigned int local_var;
|
||||
|
||||
if (fptr != NULL)
|
||||
fptr (env, &local_var);
|
||||
}
|
21
nptl/sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c
Normal file
21
nptl/sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c
Normal file
@ -0,0 +1,21 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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. */
|
||||
|
||||
/* No difference to lowlevellock.c */
|
||||
#include "lowlevellock.c"
|
21
nptl/sysdeps/unix/sysv/linux/s390/libc-lowlevelmutex.c
Normal file
21
nptl/sysdeps/unix/sysv/linux/s390/libc-lowlevelmutex.c
Normal file
@ -0,0 +1,21 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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. */
|
||||
|
||||
/* No difference to lowlevelmutex.c */
|
||||
#include "lowlevelmutex.c"
|
103
nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.c
Normal file
103
nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.c
Normal file
@ -0,0 +1,103 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 <errno.h>
|
||||
#include <sysdep.h>
|
||||
#include <lowlevellock.h>
|
||||
|
||||
|
||||
void
|
||||
___lll_lock (futex, newval)
|
||||
int *futex;
|
||||
int newval;
|
||||
{
|
||||
do
|
||||
{
|
||||
int oldval;
|
||||
|
||||
lll_futex_wait (futex, newval);
|
||||
lll_compare_and_swap (futex, oldval, newval, "lr %2,%1; ahi %2,-1");
|
||||
}
|
||||
while (newval != 0);
|
||||
|
||||
*futex = -1;
|
||||
}
|
||||
hidden_proto (___lll_lock)
|
||||
|
||||
|
||||
/* XXX Should not be in libc.so */
|
||||
int
|
||||
lll_unlock_wake_cb (futex)
|
||||
int *futex;
|
||||
{
|
||||
int oldval;
|
||||
int newval;
|
||||
|
||||
lll_compare_and_swap (futex, oldval, newval, "lr %2,%1; ahi %2,1");
|
||||
if (oldval < 0)
|
||||
lll_futex_wake (futex, 1);
|
||||
return 0;
|
||||
}
|
||||
hidden_proto (lll_unlock_wake_cb)
|
||||
|
||||
|
||||
/* XXX Should not be in libc.so */
|
||||
int
|
||||
___lll_timedwait_tid (ptid, abstime)
|
||||
int *ptid;
|
||||
const struct timespec *abstime;
|
||||
{
|
||||
int tid;
|
||||
|
||||
if (abstime == NULL || abstime->tv_nsec >= 1000000000)
|
||||
return EINVAL;
|
||||
|
||||
/* Repeat until thread terminated. */
|
||||
while ((tid = *ptid) != 0)
|
||||
{
|
||||
/* Get current time. */
|
||||
struct timeval tv;
|
||||
gettimeofday (&tv, NULL);
|
||||
|
||||
/* Determine relative timeout. */
|
||||
struct timespec rt;
|
||||
rt.tv_sec = abstime->tv_sec - tv.tv_sec;
|
||||
rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
|
||||
if (rt.tv_nsec < 0)
|
||||
{
|
||||
rt.tv_nsec += 1000000000;
|
||||
rt.tv_sec--;
|
||||
}
|
||||
/* Already timed out? */
|
||||
if (rt.tv_sec < 0)
|
||||
return ETIMEDOUT;
|
||||
|
||||
/* Wait until thread terminates. */
|
||||
int err = lll_futex_timed_wait (ptid, tid, &rt);
|
||||
|
||||
/* Woken due to timeout? */
|
||||
if (err == -ETIMEDOUT)
|
||||
/* Yes. */
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
hidden_proto (___lll_timedwait_tid)
|
294
nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h
Normal file
294
nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h
Normal file
@ -0,0 +1,294 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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. */
|
||||
|
||||
#ifndef _LOWLEVELLOCK_H
|
||||
#define _LOWLEVELLOCK_H 1
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/param.h>
|
||||
#include <bits/pthreadtypes.h>
|
||||
|
||||
#define SYS_futex 238
|
||||
#define FUTEX_WAIT 0
|
||||
#define FUTEX_WAKE 1
|
||||
|
||||
/* Initializer for compatibility lock. */
|
||||
#define LLL_MUTEX_LOCK_INITIALIZER (0)
|
||||
|
||||
#define lll_futex_wait(futex, val) \
|
||||
({ \
|
||||
register unsigned long int __r2 asm ("2") = (unsigned long int) (futex); \
|
||||
register unsigned long int __r3 asm ("3") = FUTEX_WAIT; \
|
||||
register unsigned long int __r4 asm ("4") = (unsigned long int) (val); \
|
||||
register unsigned long int __r5 asm ("5") = 0ul; \
|
||||
register unsigned long __result asm ("2"); \
|
||||
\
|
||||
__asm __volatile ("svc %b1" \
|
||||
: "=d" (__result) \
|
||||
: "i" (SYS_futex), "0" (__r2), "d" (__r3), \
|
||||
"d" (__r4), "d" (__r5) \
|
||||
: "cc", "memory" ); \
|
||||
__result; \
|
||||
})
|
||||
|
||||
|
||||
#define lll_futex_timed_wait(futex, val, timespec) \
|
||||
({ \
|
||||
register unsigned long int __r2 asm ("2") = (unsigned long int) (futex); \
|
||||
register unsigned long int __r3 asm ("3") = FUTEX_WAIT; \
|
||||
register unsigned long int __r4 asm ("4") = (unsigned long int) (val); \
|
||||
register unsigned long int __r5 asm ("5") = (unsigned long int)(timespec);\
|
||||
register unsigned long int __result asm ("2"); \
|
||||
\
|
||||
__asm __volatile ("svc %b1" \
|
||||
: "=d" (__result) \
|
||||
: "i" (SYS_futex), "0" (__r2), "d" (__r3), \
|
||||
"d" (__r4), "d" (__r5) \
|
||||
: "cc", "memory" ); \
|
||||
__result; \
|
||||
})
|
||||
|
||||
|
||||
#define lll_futex_wake(futex, nr) \
|
||||
({ \
|
||||
register unsigned long int __r2 asm ("2") = (unsigned long int) (futex); \
|
||||
register unsigned long int __r3 asm ("3") = FUTEX_WAKE; \
|
||||
register unsigned long int __r4 asm ("4") = (unsigned long int) (nr); \
|
||||
register unsigned long int __result asm ("2"); \
|
||||
\
|
||||
__asm __volatile ("svc %b1" \
|
||||
: "=d" (__result) \
|
||||
: "i" (SYS_futex), "0" (__r2), "d" (__r3), "d" (__r4) \
|
||||
: "cc", "memory" ); \
|
||||
__result; \
|
||||
})
|
||||
|
||||
|
||||
#define lll_compare_and_swap(futex, oldval, newval, operation) \
|
||||
do { \
|
||||
__typeof (futex) __futex = (futex); \
|
||||
__asm __volatile (" l %1,%0\n" \
|
||||
"0: " operation "\n" \
|
||||
" cs %1,%2,%0\n" \
|
||||
" jl 0b\n" \
|
||||
"1:" \
|
||||
: "=Q" (*__futex), "=&d" (oldval), "=&d" (newval) \
|
||||
: "m" (*__futex) : "cc" ); \
|
||||
} while (0)
|
||||
|
||||
|
||||
static inline int
|
||||
__attribute__ ((always_inline))
|
||||
__lll_mutex_trylock (int *futex)
|
||||
{
|
||||
unsigned int old;
|
||||
|
||||
__asm __volatile ("cs %0,%3,%1"
|
||||
: "=d" (old), "=Q" (*futex)
|
||||
: "0" (0), "d" (1), "m" (*futex) : "cc" );
|
||||
return old != 0;
|
||||
}
|
||||
#define lll_mutex_trylock(futex) __lll_mutex_trylock (&(futex))
|
||||
|
||||
|
||||
extern void ___lll_mutex_lock (int *, int) attribute_hidden;
|
||||
|
||||
|
||||
static inline void
|
||||
__attribute__ ((always_inline))
|
||||
__lll_mutex_lock (int *futex)
|
||||
{
|
||||
int oldval;
|
||||
int newval;
|
||||
|
||||
lll_compare_and_swap (futex, oldval, newval, "lr %2,%1; ahi %2,1");
|
||||
if (oldval > 0)
|
||||
___lll_mutex_lock (futex, newval);
|
||||
}
|
||||
#define lll_mutex_lock(futex) __lll_mutex_lock (&(futex))
|
||||
|
||||
|
||||
extern int ___lll_mutex_timedlock (int *, const struct timespec *, int)
|
||||
attribute_hidden;
|
||||
|
||||
|
||||
static inline int
|
||||
__attribute__ ((always_inline))
|
||||
__lll_mutex_timedlock (int *futex, struct timespec *abstime)
|
||||
{
|
||||
int oldval;
|
||||
int newval;
|
||||
int result = 0;
|
||||
|
||||
lll_compare_and_swap (futex, oldval, newval, "lr %2,%1; ahi %2,1");
|
||||
if (oldval > 0)
|
||||
result = ___lll_mutex_timedlock (futex, abstime, newval);
|
||||
|
||||
return result;
|
||||
}
|
||||
#define lll_mutex_timedlock(futex, abstime) \
|
||||
__lll_mutex_timedlock (&(futex), abstime)
|
||||
|
||||
|
||||
static inline void
|
||||
__attribute__ ((always_inline))
|
||||
__lll_mutex_unlock (int *futex)
|
||||
{
|
||||
int oldval;
|
||||
int newval;
|
||||
|
||||
lll_compare_and_swap (futex, oldval, newval, "slr %2,%2");
|
||||
if (oldval > 1)
|
||||
lll_futex_wake (futex, 1);
|
||||
}
|
||||
#define lll_mutex_unlock(futex) __lll_mutex_unlock(&(futex))
|
||||
|
||||
#define lll_mutex_islocked(futex) \
|
||||
(futex != 0)
|
||||
|
||||
|
||||
/* We have a separate internal lock implementation which is not tied
|
||||
to binary compatibility. */
|
||||
|
||||
/* Type for lock object. */
|
||||
typedef int lll_lock_t;
|
||||
|
||||
/* Initializers for lock. */
|
||||
#define LLL_LOCK_INITIALIZER (1)
|
||||
#define LLL_LOCK_INITIALIZER_LOCKED (0)
|
||||
|
||||
|
||||
extern int lll_unlock_wake_cb (int *__futex) attribute_hidden;
|
||||
|
||||
/* The states of a lock are:
|
||||
1 - untaken
|
||||
0 - taken by one user
|
||||
<0 - taken by more users */
|
||||
|
||||
|
||||
static inline int
|
||||
__attribute__ ((always_inline))
|
||||
__lll_trylock (int *futex)
|
||||
{
|
||||
unsigned int old;
|
||||
|
||||
__asm __volatile ("cs %0,%3,%1"
|
||||
: "=d" (old), "=Q" (*futex)
|
||||
: "0" (1), "d" (0), "m" (*futex) : "cc" );
|
||||
return old != 1;
|
||||
}
|
||||
#define lll_trylock(futex) __lll_trylock (&(futex))
|
||||
|
||||
|
||||
extern void ___lll_lock (int *, int) attribute_hidden;
|
||||
|
||||
static inline void
|
||||
__attribute__ ((always_inline))
|
||||
__lll_lock (int *futex)
|
||||
{
|
||||
int oldval;
|
||||
int newval;
|
||||
|
||||
lll_compare_and_swap (futex, oldval, newval, "lr %2,%1; ahi %2,-1");
|
||||
if (newval < 0)
|
||||
___lll_lock (futex, newval);
|
||||
}
|
||||
#define lll_lock(futex) __lll_lock (&(futex))
|
||||
|
||||
|
||||
static inline void
|
||||
__attribute__ ((always_inline))
|
||||
__lll_unlock (int *futex)
|
||||
{
|
||||
int oldval;
|
||||
int newval;
|
||||
|
||||
lll_compare_and_swap (futex, oldval, newval, "lhi %2,1");
|
||||
if (oldval < 0)
|
||||
lll_futex_wake (futex, 1);
|
||||
}
|
||||
#define lll_unlock(futex) __lll_unlock(&(futex))
|
||||
|
||||
|
||||
#define lll_islocked(futex) \
|
||||
(futex != 1)
|
||||
|
||||
|
||||
/* The kernel notifies a process with uses CLONE_CLEARTID via futex
|
||||
wakeup when the clone terminates. The memory location contains the
|
||||
thread ID while the clone is running and is reset to zero
|
||||
afterwards. */
|
||||
static inline void
|
||||
__attribute__ ((always_inline))
|
||||
__lll_wait_tid (int *ptid)
|
||||
{
|
||||
int tid;
|
||||
|
||||
while ((tid = *ptid) != 0)
|
||||
lll_futex_wait (ptid, tid);
|
||||
}
|
||||
#define lll_wait_tid(tid) __lll_wait_tid(&(tid))
|
||||
|
||||
|
||||
extern int ___lll_timedwait_tid (int *, const struct timespec *)
|
||||
attribute_hidden;
|
||||
static inline int
|
||||
__attribute__ ((always_inline))
|
||||
__lll_timedwait_tid (int *ptid, const struct timespec *abstime)
|
||||
{
|
||||
if (*ptid == 0)
|
||||
return 0;
|
||||
|
||||
return ___lll_timedwait_tid (ptid, abstime);
|
||||
}
|
||||
#define lll_timedwait_tid(tid, abstime) __lll_timedwait_tid (&(tid), abstime)
|
||||
|
||||
|
||||
static inline void
|
||||
__attribute__ ((always_inline))
|
||||
__lll_wake_tid (int *ptid)
|
||||
{
|
||||
*ptid = 0;
|
||||
lll_futex_wake (ptid, INT_MAX);
|
||||
}
|
||||
#define lll_wake_tid(tid) __lll_wake_tid (&(tid))
|
||||
|
||||
|
||||
/* Conditional variable handling. */
|
||||
|
||||
extern void __lll_cond_wait (pthread_cond_t *cond)
|
||||
attribute_hidden;
|
||||
extern int __lll_cond_timedwait (pthread_cond_t *cond,
|
||||
const struct timespec *abstime)
|
||||
attribute_hidden;
|
||||
extern void __lll_cond_wake (pthread_cond_t *cond)
|
||||
attribute_hidden;
|
||||
extern void __lll_cond_broadcast (pthread_cond_t *cond)
|
||||
attribute_hidden;
|
||||
|
||||
#define lll_cond_wait(cond) \
|
||||
__lll_cond_wait (cond)
|
||||
#define lll_cond_timedwait(cond, abstime) \
|
||||
__lll_cond_timedwait (cond, abstime)
|
||||
#define lll_cond_wake(cond) \
|
||||
__lll_cond_wake (cond)
|
||||
#define lll_cond_broadcast(cond) \
|
||||
__lll_cond_broadcast (cond)
|
||||
|
||||
#endif /* lowlevellock.h */
|
90
nptl/sysdeps/unix/sysv/linux/s390/lowlevelmutex.c
Normal file
90
nptl/sysdeps/unix/sysv/linux/s390/lowlevelmutex.c
Normal file
@ -0,0 +1,90 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 <errno.h>
|
||||
#include <sysdep.h>
|
||||
#include <lowlevellock.h>
|
||||
|
||||
|
||||
void
|
||||
___lll_mutex_lock (futex, newval)
|
||||
int *futex;
|
||||
int newval;
|
||||
{
|
||||
int oldval;
|
||||
|
||||
do
|
||||
{
|
||||
lll_futex_wait (futex, newval);
|
||||
lll_compare_and_swap (futex, oldval, newval, "lr %2,%1; ahi %2,1");
|
||||
}
|
||||
while (oldval != 0);
|
||||
|
||||
*futex = 2;
|
||||
}
|
||||
hidden_proto (___lll_mutex_lock)
|
||||
|
||||
|
||||
int
|
||||
___lll_mutex_timedlock (futex, abstime, newval)
|
||||
int *futex;
|
||||
const struct timespec *abstime;
|
||||
int newval;
|
||||
{
|
||||
/* Reject invalid timeouts. */
|
||||
if (abstime->tv_nsec >= 1000000000)
|
||||
return EINVAL;
|
||||
|
||||
int oldval;
|
||||
do
|
||||
{
|
||||
/* Get the current time. */
|
||||
struct timeval tv;
|
||||
gettimeofday (&tv, NULL);
|
||||
|
||||
/* Compute relative timeout. */
|
||||
struct timespec rt;
|
||||
rt.tv_sec = abstime->tv_sec - tv.tv_sec;
|
||||
rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
|
||||
if (rt.tv_nsec < 0)
|
||||
{
|
||||
rt.tv_nsec += 1000000000;
|
||||
--rt.tv_sec;
|
||||
}
|
||||
/* Already timed out? */
|
||||
if (rt.tv_sec < 0)
|
||||
return ETIMEDOUT;
|
||||
|
||||
/* Wait. */
|
||||
int err = lll_futex_timed_wait (futex, newval, &rt);
|
||||
|
||||
/* If timed out return with an appropriate error. */
|
||||
if (err == -ETIMEDOUT)
|
||||
return ETIMEDOUT;
|
||||
|
||||
/* XXX oldval in undefined !!! */
|
||||
lll_compare_and_swap (futex, oldval, newval, "lr %2,%1; ahi %2,1");
|
||||
}
|
||||
while (oldval != 0);
|
||||
|
||||
*futex = 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
hidden_proto (___lll_mutex_timedlock)
|
71
nptl/sysdeps/unix/sysv/linux/s390/lowlevelsem.h
Normal file
71
nptl/sysdeps/unix/sysv/linux/s390/lowlevelsem.h
Normal file
@ -0,0 +1,71 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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. */
|
||||
|
||||
#ifndef _LOWLEVELSEM_H
|
||||
#define _LOWLEVELSEM_H 1
|
||||
|
||||
#include <dl-sysdep.h>
|
||||
#include <tls.h>
|
||||
#include <lowlevellock.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
|
||||
static inline int
|
||||
__attribute__ ((always_inline))
|
||||
lll_sem_wait (sem_t *sem)
|
||||
{
|
||||
int oldval;
|
||||
int newval;
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* Atomically decrement semaphore counter if it is > 0. */
|
||||
lll_compare_and_swap ((int *) sem, oldval, newval,
|
||||
"ltr %2,%1; jnp 1f; ahi %2,-1");
|
||||
/* oldval != newval if the semaphore count has been decremented. */
|
||||
if (oldval != newval)
|
||||
return 0;
|
||||
int err = lll_futex_wait ((int *) sem, 0);
|
||||
if (err != 0 && err != -EWOULDBLOCK)
|
||||
return -err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* Not defined anywhere. */
|
||||
extern int __lll_sem_timedwait (sem_t *sem, const struct timespec *ts)
|
||||
attribute_hidden;
|
||||
#define lll_sem_timedwait(sem, timeout) \
|
||||
__lll_sem_timedwait (sem, timeout)
|
||||
#endif
|
||||
|
||||
static inline void
|
||||
__attribute__ ((always_inline))
|
||||
lll_sem_post(sem_t *sem)
|
||||
{
|
||||
int oldval;
|
||||
int newval;
|
||||
|
||||
lll_compare_and_swap ((int *) sem, oldval, newval, "lr %2,%1; ahi %2,1");
|
||||
lll_futex_wake ((int *) sem, newval);
|
||||
}
|
||||
|
||||
#endif /* lowlevelsem.h */
|
111
nptl/sysdeps/unix/sysv/linux/s390/pthread_once.c
Normal file
111
nptl/sysdeps/unix/sysv/linux/s390/pthread_once.c
Normal file
@ -0,0 +1,111 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 "pthreadP.h"
|
||||
#include <lowlevellock.h>
|
||||
|
||||
|
||||
unsigned long int __fork_generation attribute_hidden;
|
||||
|
||||
|
||||
static void
|
||||
clear_once_control (void *arg)
|
||||
{
|
||||
pthread_once_t *once_control = (pthread_once_t *) arg;
|
||||
|
||||
*once_control = 0;
|
||||
lll_futex_wake (once_control, INT_MAX);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
__pthread_once (once_control, init_routine)
|
||||
pthread_once_t *once_control;
|
||||
void (*init_routine) (void);
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
int oldval;
|
||||
int newval;
|
||||
|
||||
/* Pseudo code:
|
||||
oldval = *once_control;
|
||||
if ((oldval & 2) == 0)
|
||||
{
|
||||
newval = (oldval & 3) | __fork_generation | 1;
|
||||
*once_control = newval;
|
||||
}
|
||||
Do this atomically. */
|
||||
__asm __volatile (" l %1,%0\n"
|
||||
"0: lhi %2,2\n"
|
||||
" tml %1,2\n"
|
||||
" jnz 1f\n"
|
||||
" nr %2,%1\n"
|
||||
" ahi %2,1\n"
|
||||
" o %2,%3\n"
|
||||
" cs %1,%2,%0\n"
|
||||
" jl 0b\n"
|
||||
"1:"
|
||||
: "=Q" (*once_control), "=&d" (oldval), "=&d" (newval)
|
||||
: "m" (__fork_generation), "m" (*once_control)
|
||||
: "cc" );
|
||||
/* Check if the initialized has already been done. */
|
||||
if ((oldval & 2) != 0)
|
||||
break;
|
||||
/* Check if another thread already runs the initializer. */
|
||||
if ((oldval & 1) != 0)
|
||||
{
|
||||
/* Check whether the initializer execution was interrupted
|
||||
by a fork. */
|
||||
if (((oldval ^ newval) & -4) == 0)
|
||||
{
|
||||
/* Same generation, some other thread was faster. Wait. */
|
||||
lll_futex_wait (once_control, newval);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* This thread is the first here. Do the initialization.
|
||||
Register a cleanup handler so that in case the thread gets
|
||||
interrupted the initialization can be restarted. */
|
||||
pthread_cleanup_push (clear_once_control, once_control);
|
||||
|
||||
init_routine ();
|
||||
|
||||
pthread_cleanup_pop (0);
|
||||
|
||||
|
||||
/* Add one to *once_control. */
|
||||
__asm __volatile (" l %1,%0\n"
|
||||
"0: lr %2,%1\n"
|
||||
" ahi %2,1\n"
|
||||
" cs %1,%2,%0\n"
|
||||
" jl 0b\n"
|
||||
: "=Q" (*once_control), "=&d" (oldval), "=&d" (newval)
|
||||
: "m" (*once_control) : "cc" );
|
||||
|
||||
/* Wake up all other threads. */
|
||||
lll_futex_wake (once_control, INT_MAX);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
weak_alias (__pthread_once, pthread_once)
|
||||
strong_alias (__pthread_once, __pthread_once_internal)
|
154
nptl/sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c
Normal file
154
nptl/sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c
Normal file
@ -0,0 +1,154 @@
|
||||
/* Special .init and .fini section support for S/390.
|
||||
Copyright (C) 2003 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.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file with other
|
||||
programs, and to distribute those programs without any restriction
|
||||
coming from the use of this file. (The Lesser General Public
|
||||
License restrictions do apply in other respects; for example, they
|
||||
cover modification of the file, and distribution when not linked
|
||||
into another program.)
|
||||
|
||||
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; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* This file is compiled into assembly code which is then munged by a sed
|
||||
script into two files: crti.s and crtn.s.
|
||||
|
||||
* crti.s puts a function prologue at the beginning of the
|
||||
.init and .fini sections and defines global symbols for
|
||||
those addresses, so they can be called as functions.
|
||||
|
||||
* crtn.s puts the corresponding function epilogues
|
||||
in the .init and .fini sections. */
|
||||
|
||||
__asm__ ("\
|
||||
\n\
|
||||
#include \"defs.h\"\n\
|
||||
\n\
|
||||
/*@HEADER_ENDS*/\n\
|
||||
\n\
|
||||
/*@TESTS_BEGIN*/\n\
|
||||
\n\
|
||||
/*@TESTS_END*/\n\
|
||||
\n\
|
||||
/*@_init_PROLOG_BEGINS*/\n\
|
||||
\n\
|
||||
.section .init\n\
|
||||
#NO_APP\n\
|
||||
.align 4\n\
|
||||
.globl _init\n\
|
||||
.type _init,@function\n\
|
||||
_init:\n\
|
||||
# leaf function 0\n\
|
||||
# automatics 0\n\
|
||||
# outgoing args 0\n\
|
||||
# need frame pointer 0\n\
|
||||
# call alloca 0\n\
|
||||
# has varargs 0\n\
|
||||
# incoming args (stack) 0\n\
|
||||
# function length 36\n\
|
||||
STM 6,15,24(15)\n\
|
||||
BRAS 13,.LTN1_0\n\
|
||||
.LT1_0:\n\
|
||||
.LC13:\n\
|
||||
.long __pthread_initialize_minimal_internal-.LT1_0\n\
|
||||
.LC14:\n\
|
||||
.long __gmon_start__@GOT\n\
|
||||
.LC15:\n\
|
||||
.long _GLOBAL_OFFSET_TABLE_-.LT1_0\n\
|
||||
.LTN1_0:\n\
|
||||
LR 1,15\n\
|
||||
AHI 15,-96\n\
|
||||
ST 1,0(15)\n\
|
||||
L 12,.LC15-.LT1_0(13)\n\
|
||||
AR 12,13\n\
|
||||
L 1,.LC13-.LT1_0(13)\n\
|
||||
LA 1,0(1,13)\n\
|
||||
BASR 14,1\n\
|
||||
L 1,.LC14-.LT1_0(13)\n\
|
||||
L 1,0(1,12)\n\
|
||||
LTR 1,1\n\
|
||||
JE .L22\n\
|
||||
BASR 14,1\n\
|
||||
.L22:\n\
|
||||
#APP\n\
|
||||
.align 4,0x07\n\
|
||||
END_INIT\n\
|
||||
\n\
|
||||
/*@_init_PROLOG_ENDS*/\n\
|
||||
\n\
|
||||
/*@_init_EPILOG_BEGINS*/\n\
|
||||
.align 4\n\
|
||||
.section .init\n\
|
||||
#NO_APP\n\
|
||||
.align 4\n\
|
||||
L 4,152(15)\n\
|
||||
LM 6,15,120(15)\n\
|
||||
BR 4\n\
|
||||
#APP\n\
|
||||
END_INIT\n\
|
||||
\n\
|
||||
/*@_init_EPILOG_ENDS*/\n\
|
||||
\n\
|
||||
/*@_fini_PROLOG_BEGINS*/\n\
|
||||
.section .fini\n\
|
||||
#NO_APP\n\
|
||||
.align 4\n\
|
||||
.globl _fini\n\
|
||||
.type _fini,@function\n\
|
||||
_fini:\n\
|
||||
# leaf function 0\n\
|
||||
# automatics 0\n\
|
||||
# outgoing args 0\n\
|
||||
# need frame pointer 0\n\
|
||||
# call alloca 0\n\
|
||||
# has varargs 0\n\
|
||||
# incoming args (stack) 0\n\
|
||||
# function length 30\n\
|
||||
STM 6,15,24(15)\n\
|
||||
BRAS 13,.LTN2_0\n\
|
||||
.LT2_0:\n\
|
||||
.LC17:\n\
|
||||
.long _GLOBAL_OFFSET_TABLE_-.LT2_0\n\
|
||||
.LTN2_0:\n\
|
||||
LR 1,15\n\
|
||||
AHI 15,-96\n\
|
||||
ST 1,0(15)\n\
|
||||
L 12,.LC17-.LT2_0(13)\n\
|
||||
AR 12,13\n\
|
||||
#APP\n\
|
||||
.align 4,0x07\n\
|
||||
END_FINI\n\
|
||||
\n\
|
||||
/*@_fini_PROLOG_ENDS*/\n\
|
||||
\n\
|
||||
/*@_fini_EPILOG_BEGINS*/\n\
|
||||
.align 4\n\
|
||||
.section .fini\n\
|
||||
#NO_APP\n\
|
||||
.align 4\n\
|
||||
L 4,152(15)\n\
|
||||
LM 6,15,120(15)\n\
|
||||
BR 4\n\
|
||||
#APP\n\
|
||||
END_FINI\n\
|
||||
\n\
|
||||
/*@_fini_EPILOG_ENDS*/\n\
|
||||
\n\
|
||||
/*@TRAILER_BEGINS*/\
|
||||
");
|
44
nptl/sysdeps/unix/sysv/linux/s390/s390-32/pt-vfork.S
Normal file
44
nptl/sysdeps/unix/sysv/linux/s390/s390-32/pt-vfork.S
Normal file
@ -0,0 +1,44 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 <sysdep.h>
|
||||
#define _ERRNO_H 1
|
||||
#include <bits/errno.h>
|
||||
#include <kernel-features.h>
|
||||
#include <bits/wordsize.h>
|
||||
|
||||
/* Clone the calling process, but without copying the whole address space.
|
||||
The calling process is suspended until the new process exits or is
|
||||
replaced by a call to `execve'. Return -1 for errors, 0 to the new process,
|
||||
and the process ID of the new process to the old process. */
|
||||
|
||||
ENTRY (__vfork)
|
||||
/* Do vfork system call. */
|
||||
svc SYS_ify (vfork)
|
||||
|
||||
/* Check for error. */
|
||||
lhi %r4,-4095
|
||||
clr %r2,%r4
|
||||
jnl SYSCALL_ERROR_LABEL
|
||||
|
||||
/* Normal return. */
|
||||
br %r14
|
||||
PSEUDO_END(__vfork)
|
||||
|
||||
weak_alias (__vfork, vfork)
|
99
nptl/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h
Normal file
99
nptl/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h
Normal file
@ -0,0 +1,99 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
|
||||
|
||||
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 <sysdep.h>
|
||||
#include <tls.h>
|
||||
#ifndef __ASSEMBLER__
|
||||
# include <nptl/pthreadP.h>
|
||||
#endif
|
||||
|
||||
#if !defined NOT_IN_libc || defined IS_IN_libpthread
|
||||
|
||||
# undef PSEUDO
|
||||
# define PSEUDO(name, syscall_name, args) \
|
||||
.text; \
|
||||
L(pseudo_cancel): \
|
||||
STM_##args \
|
||||
stm %r12,%r15,48(%r15); \
|
||||
lr %r14,%r15; \
|
||||
ahi %r15,-96; \
|
||||
st %r14,0(%r15); \
|
||||
basr %r13,0; \
|
||||
0: l %r1,1f-0b(%r13); \
|
||||
bas %r14,0(%r1,%r13); \
|
||||
lr %r0,%r2; \
|
||||
LM_##args \
|
||||
DO_CALL(syscall_name, args); \
|
||||
l %r1,2f-0b(%r13); \
|
||||
lr %r12,%r2; \
|
||||
lr %r2,%r0; \
|
||||
bas %r14,0(%r1,%r13); \
|
||||
lr %r2,%r12; \
|
||||
lm %r12,%r15,48+96(%r15); \
|
||||
j L(pseudo_check); \
|
||||
1: .long CENABLE-0b; \
|
||||
2: .long CDISABLE-0b; \
|
||||
ENTRY(name) \
|
||||
SINGLE_THREAD_P(%r1) \
|
||||
jne L(pseudo_cancel); \
|
||||
DO_CALL(syscall_name, args); \
|
||||
L(pseudo_check): \
|
||||
lhi %r4,-4095; \
|
||||
clr %r2,%r4; \
|
||||
jnl SYSCALL_ERROR_LABEL; \
|
||||
L(pseudo_end):
|
||||
|
||||
# ifdef IS_IN_libpthread
|
||||
# define CENABLE __pthread_enable_asynccancel
|
||||
# define CDISABLE __pthread_disable_asynccancel
|
||||
# else
|
||||
# define CENABLE __libc_enable_asynccancel
|
||||
# define CDISABLE __libc_disable_asynccancel
|
||||
# endif
|
||||
|
||||
#define STM_0 /* Nothing */
|
||||
#define STM_1 st %r2,8(%r15);
|
||||
#define STM_2 stm %r2,%r3,8(%r15);
|
||||
#define STM_3 stm %r2,%r4,8(%r15);
|
||||
#define STM_4 stm %r2,%r5,8(%r15);
|
||||
#define STM_5 stm %r2,%r5,8(%r15);
|
||||
|
||||
#define LM_0 /* Nothing */
|
||||
#define LM_1 l %r2,8+96(%r15);
|
||||
#define LM_2 lm %r2,%r3,8+96(%r15);
|
||||
#define LM_3 lm %r2,%r4,8+96(%r15);
|
||||
#define LM_4 lm %r2,%r5,8+96(%r15);
|
||||
#define LM_5 lm %r2,%r5,8+96(%r15);
|
||||
|
||||
# ifndef __ASSEMBLER__
|
||||
# define SINGLE_THREAD_P \
|
||||
__builtin_expect (THREAD_GETMEM (THREAD_SELF, \
|
||||
header.data.multiple_threads) == 0, 1)
|
||||
# else
|
||||
# define SINGLE_THREAD_P(reg) \
|
||||
ear reg,%a0; \
|
||||
icm reg,15,MULTIPLE_THREADS_OFFSET(reg);
|
||||
# endif
|
||||
|
||||
#elif !defined __ASSEMBLER__
|
||||
|
||||
/* This code should never be used but we define it anyhow. */
|
||||
# define SINGLE_THREAD_P (1)
|
||||
|
||||
#endif
|
136
nptl/sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c
Normal file
136
nptl/sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c
Normal file
@ -0,0 +1,136 @@
|
||||
/* Special .init and .fini section support for 64 bit S/390.
|
||||
Copyright (C) 2003 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.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file with other
|
||||
programs, and to distribute those programs without any restriction
|
||||
coming from the use of this file. (The Lesser General Public
|
||||
License restrictions do apply in other respects; for example, they
|
||||
cover modification of the file, and distribution when not linked
|
||||
into another program.)
|
||||
|
||||
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; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* This file is compiled into assembly code which is then munged by a sed
|
||||
script into two files: crti.s and crtn.s.
|
||||
|
||||
* crti.s puts a function prologue at the beginning of the
|
||||
.init and .fini sections and defines global symbols for
|
||||
those addresses, so they can be called as functions.
|
||||
|
||||
* crtn.s puts the corresponding function epilogues
|
||||
in the .init and .fini sections. */
|
||||
|
||||
__asm__ ("\
|
||||
\n\
|
||||
#include \"defs.h\"\n\
|
||||
\n\
|
||||
/*@HEADER_ENDS*/\n\
|
||||
\n\
|
||||
/*@TESTS_BEGIN*/\n\
|
||||
\n\
|
||||
/*@TESTS_END*/\n\
|
||||
\n\
|
||||
/*@_init_PROLOG_BEGINS*/\n\
|
||||
\n\
|
||||
.section .init\n\
|
||||
#NO_APP\n\
|
||||
.align 4\n\
|
||||
.globl _init\n\
|
||||
.type _init,@function\n\
|
||||
_init:\n\
|
||||
# leaf function 0\n\
|
||||
# automatics 0\n\
|
||||
# outgoing args 0\n\
|
||||
# need frame pointer 0\n\
|
||||
# call alloca 0\n\
|
||||
# has varargs 0\n\
|
||||
# incoming args (stack) 0\n\
|
||||
# function length 36\n\
|
||||
STMG 6,15,48(15)\n\
|
||||
LGR 1,15\n\
|
||||
AGHI 15,-160\n\
|
||||
STG 1,0(15)\n\
|
||||
LARL 12,_GLOBAL_OFFSET_TABLE_\n\
|
||||
BRASL 14,__pthread_initialize_minimal_internal\n\
|
||||
LARL 1,__gmon_start__@GOTENT\n\
|
||||
LG 1,0(1)\n\
|
||||
LTGR 1,1\n\
|
||||
JE .L22\n\
|
||||
BASR 14,1\n\
|
||||
.L22:\n\
|
||||
#APP\n\
|
||||
.align 4,0x07\n\
|
||||
END_INIT\n\
|
||||
\n\
|
||||
/*@_init_PROLOG_ENDS*/\n\
|
||||
\n\
|
||||
/*@_init_EPILOG_BEGINS*/\n\
|
||||
.align 4\n\
|
||||
.section .init\n\
|
||||
#NO_APP\n\
|
||||
.align 4\n\
|
||||
LG 4,272(15)\n\
|
||||
LMG 6,15,208(15)\n\
|
||||
BR 4\n\
|
||||
#APP\n\
|
||||
END_INIT\n\
|
||||
\n\
|
||||
/*@_init_EPILOG_ENDS*/\n\
|
||||
\n\
|
||||
/*@_fini_PROLOG_BEGINS*/\n\
|
||||
.section .fini\n\
|
||||
#NO_APP\n\
|
||||
.align 4\n\
|
||||
.globl _fini\n\
|
||||
.type _fini,@function\n\
|
||||
_fini:\n\
|
||||
# leaf function 0\n\
|
||||
# automatics 0\n\
|
||||
# outgoing args 0\n\
|
||||
# need frame pointer 0\n\
|
||||
# call alloca 0\n\
|
||||
# has varargs 0\n\
|
||||
# incoming args (stack) 0\n\
|
||||
# function length 30\n\
|
||||
STMG 6,15,48(15)\n\
|
||||
LGR 1,15\n\
|
||||
AGHI 15,-160\n\
|
||||
STG 1,0(15)\n\
|
||||
LARL 12,_GLOBAL_OFFSET_TABLE_\n\
|
||||
#APP\n\
|
||||
.align 4,0x07\n\
|
||||
END_FINI\n\
|
||||
\n\
|
||||
/*@_fini_PROLOG_ENDS*/\n\
|
||||
\n\
|
||||
/*@_fini_EPILOG_BEGINS*/\n\
|
||||
.align 4\n\
|
||||
.section .fini\n\
|
||||
#NO_APP\n\
|
||||
.align 4\n\
|
||||
LG 4,272(15)\n\
|
||||
LMG 6,15,208(15)\n\
|
||||
BR 4\n\
|
||||
#APP\n\
|
||||
END_FINI\n\
|
||||
\n\
|
||||
/*@_fini_EPILOG_ENDS*/\n\
|
||||
\n\
|
||||
/*@TRAILER_BEGINS*/\n\
|
||||
");
|
44
nptl/sysdeps/unix/sysv/linux/s390/s390-64/pt-vfork.S
Normal file
44
nptl/sysdeps/unix/sysv/linux/s390/s390-64/pt-vfork.S
Normal file
@ -0,0 +1,44 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 <sysdep.h>
|
||||
#define _ERRNO_H 1
|
||||
#include <bits/errno.h>
|
||||
#include <kernel-features.h>
|
||||
#include <bits/wordsize.h>
|
||||
|
||||
/* Clone the calling process, but without copying the whole address space.
|
||||
The calling process is suspended until the new process exits or is
|
||||
replaced by a call to `execve'. Return -1 for errors, 0 to the new process,
|
||||
and the process ID of the new process to the old process. */
|
||||
|
||||
ENTRY (__vfork)
|
||||
/* Do vfork system call. */
|
||||
svc SYS_ify (vfork)
|
||||
|
||||
/* Check for error. */
|
||||
lghi %r4,-4095
|
||||
clgr %r2,%r4
|
||||
jnl SYSCALL_ERROR_LABEL
|
||||
|
||||
/* Normal return. */
|
||||
br %r14
|
||||
PSEUDO_END(__vfork)
|
||||
|
||||
weak_alias (__vfork, vfork)
|
98
nptl/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h
Normal file
98
nptl/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h
Normal file
@ -0,0 +1,98 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
|
||||
|
||||
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 <sysdep.h>
|
||||
#include <tls.h>
|
||||
#ifndef __ASSEMBLER__
|
||||
# include <nptl/pthreadP.h>
|
||||
#endif
|
||||
|
||||
#if !defined NOT_IN_libc || defined IS_IN_libpthread
|
||||
|
||||
# undef PSEUDO
|
||||
# define PSEUDO(name, syscall_name, args) \
|
||||
.text; \
|
||||
L(pseudo_cancel): \
|
||||
STM_##args \
|
||||
stmg %r13,%r15,104(%r15); \
|
||||
lgr %r14,%r15; \
|
||||
aghi %r15,-160; \
|
||||
stg %r14,0(%r15); \
|
||||
brasl %r14,CENABLE; \
|
||||
lgr %r0,%r2; \
|
||||
LM_##args \
|
||||
DO_CALL(syscall_name, args); \
|
||||
lgr %r13,%r2; \
|
||||
lgr %r2,%r0; \
|
||||
brasl %r14,CDISABLE; \
|
||||
lgr %r2,%r13; \
|
||||
lmg %r13,%r15,104+160(%r15); \
|
||||
j L(pseudo_check); \
|
||||
ENTRY(name) \
|
||||
SINGLE_THREAD_P \
|
||||
jne L(pseudo_cancel); \
|
||||
DO_CALL(syscall_name, args); \
|
||||
L(pseudo_check): \
|
||||
lghi %r4,-4095; \
|
||||
clgr %r2,%r4; \
|
||||
jgnl SYSCALL_ERROR_LABEL; \
|
||||
L(pseudo_end):
|
||||
|
||||
# ifdef IS_IN_libpthread
|
||||
# define CENABLE __pthread_enable_asynccancel
|
||||
# define CDISABLE __pthread_disable_asynccancel
|
||||
# define __local_multiple_threads __pthread_multiple_threads
|
||||
# else
|
||||
# define CENABLE __libc_enable_asynccancel
|
||||
# define CDISABLE __libc_disable_asynccancel
|
||||
# define __local_multiple_threads __libc_multiple_threads
|
||||
# endif
|
||||
|
||||
#define STM_0 /* Nothing */
|
||||
#define STM_1 stg %r2,16(%r15);
|
||||
#define STM_2 stmg %r2,%r3,16(%r15);
|
||||
#define STM_3 stmg %r2,%r4,16(%r15);
|
||||
#define STM_4 stmg %r2,%r5,16(%r15);
|
||||
#define STM_5 stmg %r2,%r5,16(%r15);
|
||||
|
||||
#define LM_0 /* Nothing */
|
||||
#define LM_1 lg %r2,16+160(%r15);
|
||||
#define LM_2 lmg %r2,%r3,16+160(%r15);
|
||||
#define LM_3 lmg %r2,%r4,16+160(%r15);
|
||||
#define LM_4 lmg %r2,%r5,16+160(%r15);
|
||||
#define LM_5 lmg %r2,%r5,16+160(%r15);
|
||||
|
||||
# ifndef __ASSEMBLER__
|
||||
# define SINGLE_THREAD_P \
|
||||
__builtin_expect (THREAD_GETMEM (THREAD_SELF, \
|
||||
header.data.multiple_threads) == 0, 1)
|
||||
# else
|
||||
# define SINGLE_THREAD_P \
|
||||
ear %r1,%a0; \
|
||||
sllg %r1,%r1,32; \
|
||||
ear %r1,%a1; \
|
||||
icm %r1,15,MULTIPLE_THREADS_OFFSET(%r1);
|
||||
# endif
|
||||
|
||||
#elif !defined __ASSEMBLER__
|
||||
|
||||
/* This code should never be used but we define it anyhow. */
|
||||
# define SINGLE_THREAD_P (1)
|
||||
|
||||
#endif
|
41
nptl/sysdeps/unix/sysv/linux/s390/sem_post.c
Normal file
41
nptl/sysdeps/unix/sysv/linux/s390/sem_post.c
Normal file
@ -0,0 +1,41 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 <errno.h>
|
||||
#include <sysdep.h>
|
||||
#include <lowlevelsem.h>
|
||||
#include <internaltypes.h>
|
||||
|
||||
#include <shlib-compat.h>
|
||||
|
||||
|
||||
int
|
||||
__new_sem_post (sem_t *sem)
|
||||
{
|
||||
int oldval;
|
||||
int newval;
|
||||
|
||||
lll_compare_and_swap ((int *) sem, oldval, newval, "lr %2,%1; ahi %2,1");
|
||||
lll_futex_wake ((int *) sem, newval);
|
||||
}
|
||||
versioned_symbol (libpthread, __new_sem_post, sem_post, GLIBC_2_1);
|
||||
#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
|
||||
strong_alias (__new_sem_post, __old_sem_post)
|
||||
compat_symbol (libpthread, __old_sem_post, sem_post, GLIBC_2_0);
|
||||
#endif
|
88
nptl/sysdeps/unix/sysv/linux/s390/sem_timedwait.c
Normal file
88
nptl/sysdeps/unix/sysv/linux/s390/sem_timedwait.c
Normal file
@ -0,0 +1,88 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 <errno.h>
|
||||
#include <sysdep.h>
|
||||
#include <lowlevelsem.h>
|
||||
#include <internaltypes.h>
|
||||
|
||||
#include <shlib-compat.h>
|
||||
|
||||
|
||||
int
|
||||
sem_timedwait (sem, abstime)
|
||||
sem_t *sem;
|
||||
const struct timespec *abstime;
|
||||
{
|
||||
int oldval, newval;
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* Atomically decrement semaphore counter if it is > 0. */
|
||||
lll_compare_and_swap ((int *) sem, oldval, newval,
|
||||
"ltr %2,%1; jnp 1f; ahi %2,-1");
|
||||
/* oldval != newval if the semaphore count has been decremented. */
|
||||
if (oldval != newval)
|
||||
return 0;
|
||||
|
||||
/* Check for invalid timeout values. */
|
||||
if (abstime->tv_nsec >= 1000000000)
|
||||
{
|
||||
__set_errno(EINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get the current time. */
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
/* Compute the relative timeout. */
|
||||
struct timespec rt;
|
||||
rt.tv_sec = abstime->tv_sec - tv.tv_sec;
|
||||
rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
|
||||
if (rt.tv_nsec < 0)
|
||||
{
|
||||
rt.tv_nsec += 1000000000;
|
||||
rt.tv_sec--;
|
||||
}
|
||||
/* Already timed out. */
|
||||
if (rt.tv_sec < 0)
|
||||
{
|
||||
__set_errno(ETIMEDOUT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Do wait. */
|
||||
int err = lll_futex_timed_wait ((int *) sem, 0, &rt);
|
||||
|
||||
/* Returned after timing out? */
|
||||
if (err == -ETIMEDOUT)
|
||||
{
|
||||
__set_errno (ETIMEDOUT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Handle EINTR. */
|
||||
if (err != 0 && err != -EWOULDBLOCK)
|
||||
{
|
||||
__set_errno (-err);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
49
nptl/sysdeps/unix/sysv/linux/s390/sem_trywait.c
Normal file
49
nptl/sysdeps/unix/sysv/linux/s390/sem_trywait.c
Normal file
@ -0,0 +1,49 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 <errno.h>
|
||||
#include <sysdep.h>
|
||||
#include <lowlevelsem.h>
|
||||
#include <internaltypes.h>
|
||||
|
||||
#include <shlib-compat.h>
|
||||
|
||||
|
||||
int
|
||||
__new_sem_trywait (sem_t *sem)
|
||||
{
|
||||
int oldval;
|
||||
int newval;
|
||||
|
||||
/* Atomically decrement sem counter if it is > 0. */
|
||||
lll_compare_and_swap ((int *) sem, oldval, newval,
|
||||
"ltr %2,%1; jnp 1f; ahi %2,-1");
|
||||
/* oldval != newval if the semaphore count has been decremented. */
|
||||
if (oldval == newval)
|
||||
{
|
||||
__set_errno (EAGAIN);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
versioned_symbol (libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1);
|
||||
#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
|
||||
strong_alias (__new_sem_trywait, __old_sem_trywait)
|
||||
compat_symbol (libpthread, __old_sem_trywait, sem_trywait, GLIBC_2_0);
|
||||
#endif
|
60
nptl/sysdeps/unix/sysv/linux/s390/sem_wait.c
Normal file
60
nptl/sysdeps/unix/sysv/linux/s390/sem_wait.c
Normal file
@ -0,0 +1,60 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
|
||||
|
||||
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 <errno.h>
|
||||
#include <sysdep.h>
|
||||
#include <lowlevelsem.h>
|
||||
#include <internaltypes.h>
|
||||
|
||||
#include <shlib-compat.h>
|
||||
|
||||
|
||||
int
|
||||
__new_sem_wait (sem_t *sem)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
int oldval;
|
||||
int newval;
|
||||
|
||||
/* Atomically decrement semaphore counter if it is > 0. */
|
||||
lll_compare_and_swap ((int *) sem, oldval, newval,
|
||||
"ltr %2,%1; jnp 1f; ahi %2,-1");
|
||||
|
||||
/* oldval != newval if the semaphore count has been decremented. */
|
||||
if (oldval != newval)
|
||||
return 0;
|
||||
|
||||
/* Do wait. */
|
||||
int err = lll_futex_wait ((int *) sem, 0);
|
||||
|
||||
/* Handle EINTR. */
|
||||
if (err != 0 && err != -EWOULDBLOCK)
|
||||
{
|
||||
__set_errno (-err);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1);
|
||||
#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
|
||||
strong_alias (__new_sem_wait, __old_sem_wait)
|
||||
compat_symbol (libpthread, __old_sem_wait, sem_wait, GLIBC_2_0);
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user