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:
Ulrich Drepper 2003-02-05 09:54:24 +00:00
parent ec609a8e77
commit a88c926368
48 changed files with 3394 additions and 4 deletions

View File

@ -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

View File

@ -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)

View File

@ -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.

View File

@ -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. */

View File

@ -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. */

View 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;
}

View 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);

View 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);

View 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);

View 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);

View 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)

View 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;
}

View 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;
}

View 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)

View 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)

View 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

View 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

View 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. */

View 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;
}

View 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;
}

View 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)

View 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)

View File

@ -0,0 +1,4 @@
#include <sysdep.h>
#include <tls.h>
MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads)

View 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
View 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 */

View 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 */

View 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;

View 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>

View 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 */

View 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"

View 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);
}

View 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"

View 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"

View 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)

View 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 */

View 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)

View 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 */

View 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)

View 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*/\
");

View 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)

View 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

View 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\
");

View 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)

View 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

View 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

View 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;
}
}
}

View 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

View 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