Update.
authorUlrich Drepper <drepper@redhat.com>
Wed, 5 Feb 2003 09:54:24 +0000 (09:54 +0000)
committerUlrich Drepper <drepper@redhat.com>
Wed, 5 Feb 2003 09:54:24 +0000 (09:54 +0000)
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.

48 files changed:
linuxthreads/ChangeLog
linuxthreads/sysdeps/pthread/bits/libc-lock.h
nptl/ChangeLog
nptl/allocatestack.c
nptl/init.c
nptl/sysdeps/pthread/pthread_barrier_wait.c [new file with mode: 0644]
nptl/sysdeps/pthread/pthread_cond_broadcast.c [new file with mode: 0644]
nptl/sysdeps/pthread/pthread_cond_signal.c [new file with mode: 0644]
nptl/sysdeps/pthread/pthread_cond_timedwait.c [new file with mode: 0644]
nptl/sysdeps/pthread/pthread_cond_wait.c [new file with mode: 0644]
nptl/sysdeps/pthread/pthread_rwlock_rdlock.c [new file with mode: 0644]
nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c [new file with mode: 0644]
nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c [new file with mode: 0644]
nptl/sysdeps/pthread/pthread_rwlock_unlock.c [new file with mode: 0644]
nptl/sysdeps/pthread/pthread_rwlock_wrlock.c [new file with mode: 0644]
nptl/sysdeps/s390/Makefile [new file with mode: 0644]
nptl/sysdeps/s390/bits/atomic.h [new file with mode: 0644]
nptl/sysdeps/s390/pthread_spin_init.c [new file with mode: 0644]
nptl/sysdeps/s390/pthread_spin_lock.c [new file with mode: 0644]
nptl/sysdeps/s390/pthread_spin_trylock.c [new file with mode: 0644]
nptl/sysdeps/s390/pthread_spin_unlock.c [new file with mode: 0644]
nptl/sysdeps/s390/pthreaddef.h [new file with mode: 0644]
nptl/sysdeps/s390/tcb-offsets.sym [new file with mode: 0644]
nptl/sysdeps/s390/td_ta_map_lwp2thr.c [new file with mode: 0644]
nptl/sysdeps/s390/tls.h [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/s390/bits/semaphore.h [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/s390/createthread.c [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/s390/dl-sysdep.h [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/s390/fork.c [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/s390/jmp-unwind.c [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/s390/libc-lowlevelmutex.c [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.c [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/s390/lowlevelmutex.c [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/s390/lowlevelsem.h [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/s390/pthread_once.c [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/s390/s390-32/pt-vfork.S [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/s390/s390-64/pt-vfork.S [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/s390/sem_post.c [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/s390/sem_timedwait.c [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/s390/sem_trywait.c [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/s390/sem_wait.c [new file with mode: 0644]

index 2678a6d..648bd31 100644 (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
index 136b1a8..a9a98c5 100644 (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)
 
index 215ec8d..40f2dd5 100644 (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.
index e50d2b2..94d4525 100644 (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.  */
index 7704e9f..92afd09 100644 (file)
 #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.  */
diff --git a/nptl/sysdeps/pthread/pthread_barrier_wait.c b/nptl/sysdeps/pthread/pthread_barrier_wait.c
new file mode 100644 (file)
index 0000000..69274d6
--- /dev/null
@@ -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;
+}
diff --git a/nptl/sysdeps/pthread/pthread_cond_broadcast.c b/nptl/sysdeps/pthread/pthread_cond_broadcast.c
new file mode 100644 (file)
index 0000000..7ae1602
--- /dev/null
@@ -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);
diff --git a/nptl/sysdeps/pthread/pthread_cond_signal.c b/nptl/sysdeps/pthread/pthread_cond_signal.c
new file mode 100644 (file)
index 0000000..1a035fe
--- /dev/null
@@ -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);
diff --git a/nptl/sysdeps/pthread/pthread_cond_timedwait.c b/nptl/sysdeps/pthread/pthread_cond_timedwait.c
new file mode 100644 (file)
index 0000000..797d244
--- /dev/null
@@ -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);
diff --git a/nptl/sysdeps/pthread/pthread_cond_wait.c b/nptl/sysdeps/pthread/pthread_cond_wait.c
new file mode 100644 (file)
index 0000000..d0b63bd
--- /dev/null
@@ -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);
diff --git a/nptl/sysdeps/pthread/pthread_rwlock_rdlock.c b/nptl/sysdeps/pthread/pthread_rwlock_rdlock.c
new file mode 100644 (file)
index 0000000..b556ccf
--- /dev/null
@@ -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)
diff --git a/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c b/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c
new file mode 100644 (file)
index 0000000..4f7b78d
--- /dev/null
@@ -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;
+}
diff --git a/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c b/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c
new file mode 100644 (file)
index 0000000..4c0dc38
--- /dev/null
@@ -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;
+}
diff --git a/nptl/sysdeps/pthread/pthread_rwlock_unlock.c b/nptl/sysdeps/pthread/pthread_rwlock_unlock.c
new file mode 100644 (file)
index 0000000..325007e
--- /dev/null
@@ -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)
diff --git a/nptl/sysdeps/pthread/pthread_rwlock_wrlock.c b/nptl/sysdeps/pthread/pthread_rwlock_wrlock.c
new file mode 100644 (file)
index 0000000..024b671
--- /dev/null
@@ -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)
diff --git a/nptl/sysdeps/s390/Makefile b/nptl/sysdeps/s390/Makefile
new file mode 100644 (file)
index 0000000..fff17db
--- /dev/null
@@ -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
diff --git a/nptl/sysdeps/s390/bits/atomic.h b/nptl/sysdeps/s390/bits/atomic.h
new file mode 100644 (file)
index 0000000..375ae0d
--- /dev/null
@@ -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
diff --git a/nptl/sysdeps/s390/pthread_spin_init.c b/nptl/sysdeps/s390/pthread_spin_init.c
new file mode 100644 (file)
index 0000000..814bb48
--- /dev/null
@@ -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.  */
diff --git a/nptl/sysdeps/s390/pthread_spin_lock.c b/nptl/sysdeps/s390/pthread_spin_lock.c
new file mode 100644 (file)
index 0000000..7d0067b
--- /dev/null
@@ -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;
+}
diff --git a/nptl/sysdeps/s390/pthread_spin_trylock.c b/nptl/sysdeps/s390/pthread_spin_trylock.c
new file mode 100644 (file)
index 0000000..8ed0a36
--- /dev/null
@@ -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;
+}
diff --git a/nptl/sysdeps/s390/pthread_spin_unlock.c b/nptl/sysdeps/s390/pthread_spin_unlock.c
new file mode 100644 (file)
index 0000000..a59c945
--- /dev/null
@@ -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)
diff --git a/nptl/sysdeps/s390/pthreaddef.h b/nptl/sysdeps/s390/pthreaddef.h
new file mode 100644 (file)
index 0000000..17ef4dc
--- /dev/null
@@ -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)
diff --git a/nptl/sysdeps/s390/tcb-offsets.sym b/nptl/sysdeps/s390/tcb-offsets.sym
new file mode 100644 (file)
index 0000000..aee6be2
--- /dev/null
@@ -0,0 +1,4 @@
+#include <sysdep.h>
+#include <tls.h>
+
+MULTIPLE_THREADS_OFFSET                offsetof (tcbhead_t, multiple_threads)
diff --git a/nptl/sysdeps/s390/td_ta_map_lwp2thr.c b/nptl/sysdeps/s390/td_ta_map_lwp2thr.c
new file mode 100644 (file)
index 0000000..d12328f
--- /dev/null
@@ -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;
+}
diff --git a/nptl/sysdeps/s390/tls.h b/nptl/sysdeps/s390/tls.h
new file mode 100644 (file)
index 0000000..fd43564
--- /dev/null
@@ -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 */
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h
new file mode 100644 (file)
index 0000000..7c207be
--- /dev/null
@@ -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 */
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/bits/semaphore.h b/nptl/sysdeps/unix/sysv/linux/s390/bits/semaphore.h
new file mode 100644 (file)
index 0000000..b30dbe5
--- /dev/null
@@ -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;
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/createthread.c b/nptl/sysdeps/unix/sysv/linux/s390/createthread.c
new file mode 100644 (file)
index 0000000..9defac6
--- /dev/null
@@ -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>
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/dl-sysdep.h b/nptl/sysdeps/unix/sysv/linux/s390/dl-sysdep.h
new file mode 100644 (file)
index 0000000..9a19d68
--- /dev/null
@@ -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 */
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/fork.c b/nptl/sysdeps/unix/sysv/linux/s390/fork.c
new file mode 100644 (file)
index 0000000..06635ab
--- /dev/null
@@ -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"
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/jmp-unwind.c b/nptl/sysdeps/unix/sysv/linux/s390/jmp-unwind.c
new file mode 100644 (file)
index 0000000..e41c12f
--- /dev/null
@@ -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);
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c b/nptl/sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c
new file mode 100644 (file)
index 0000000..40b5c3e
--- /dev/null
@@ -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"
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/libc-lowlevelmutex.c b/nptl/sysdeps/unix/sysv/linux/s390/libc-lowlevelmutex.c
new file mode 100644 (file)
index 0000000..38f11ba
--- /dev/null
@@ -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"
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.c b/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.c
new file mode 100644 (file)
index 0000000..42ed830
--- /dev/null
@@ -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)
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h
new file mode 100644 (file)
index 0000000..13cfbd6
--- /dev/null
@@ -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 */
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/lowlevelmutex.c b/nptl/sysdeps/unix/sysv/linux/s390/lowlevelmutex.c
new file mode 100644 (file)
index 0000000..3f1889b
--- /dev/null
@@ -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)
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/lowlevelsem.h b/nptl/sysdeps/unix/sysv/linux/s390/lowlevelsem.h
new file mode 100644 (file)
index 0000000..720fef4
--- /dev/null
@@ -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 */
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/pthread_once.c b/nptl/sysdeps/unix/sysv/linux/s390/pthread_once.c
new file mode 100644 (file)
index 0000000..f29e23f
--- /dev/null
@@ -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)
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c b/nptl/sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c
new file mode 100644 (file)
index 0000000..40d4d50
--- /dev/null
@@ -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*/\
+");
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/s390-32/pt-vfork.S b/nptl/sysdeps/unix/sysv/linux/s390/s390-32/pt-vfork.S
new file mode 100644 (file)
index 0000000..67a5bc6
--- /dev/null
@@ -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)
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h
new file mode 100644 (file)
index 0000000..7704bf2
--- /dev/null
@@ -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
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c b/nptl/sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c
new file mode 100644 (file)
index 0000000..a102d07
--- /dev/null
@@ -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\
+       ");
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/s390-64/pt-vfork.S b/nptl/sysdeps/unix/sysv/linux/s390/s390-64/pt-vfork.S
new file mode 100644 (file)
index 0000000..e45165e
--- /dev/null
@@ -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)
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h
new file mode 100644 (file)
index 0000000..5b99967
--- /dev/null
@@ -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
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/sem_post.c b/nptl/sysdeps/unix/sysv/linux/s390/sem_post.c
new file mode 100644 (file)
index 0000000..4c26857
--- /dev/null
@@ -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
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/sem_timedwait.c b/nptl/sysdeps/unix/sysv/linux/s390/sem_timedwait.c
new file mode 100644 (file)
index 0000000..7236842
--- /dev/null
@@ -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;
+       }
+    }
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/sem_trywait.c b/nptl/sysdeps/unix/sysv/linux/s390/sem_trywait.c
new file mode 100644 (file)
index 0000000..0fa047b
--- /dev/null
@@ -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
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/sem_wait.c b/nptl/sysdeps/unix/sysv/linux/s390/sem_wait.c
new file mode 100644 (file)
index 0000000..7050bad
--- /dev/null
@@ -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