[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

First cut of PowerPC support in NPTL



I have been working on adding support for PowerPC in NPTL.  The patch
below shows where I am up to with it.  I am sending it out at this
stage in the hope of getting some useful comments and criticism, even
though it is not finished or working yet.  It mostly compiles
successfully except for a few things such as the #error "Implement me"
in allocatestack.c.  The stuff that I have done so far should support
both 32-bit and 64-bit PowerPC, but I have only compiled it on PPC32.

I am also going to have to fix the kernel so that the clone system
call handles CLONE_SETTLS, and the glibc clone implementation so that
it passes the child_tid, parent_tid and child_tls arguments to the
kernel.

Paul.

diff -urN orig/nptl/init.c libc/nptl/init.c
--- orig/nptl/init.c	2003-02-27 14:57:23.000000000 +1100
+++ libc/nptl/init.c	2003-03-07 09:32:07.000000000 +1100
@@ -37,6 +37,8 @@
    having the definition remove these lines.  */
 #if defined __s390__
 # define __NR_set_tid_address	252
+#elif defined __powerpc__
+# define __NR_set_tid_address	232
 #else
 # define __NR_set_tid_address	258
 #endif
diff -urN orig/nptl/sysdeps/powerpc/Makefile libc/nptl/sysdeps/powerpc/Makefile
--- orig/nptl/sysdeps/powerpc/Makefile	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/powerpc/Makefile	Wed Mar 05 16:03:37 2003
@@ -0,0 +1,21 @@
+# Copyright (C) 2002, 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
diff -urN orig/nptl/sysdeps/powerpc/bits/atomic.h libc/nptl/sysdeps/powerpc/bits/atomic.h
--- orig/nptl/sysdeps/powerpc/bits/atomic.h	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/powerpc/bits/atomic.h	Fri Mar 07 09:43:05 2003
@@ -0,0 +1,100 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Mackerras <paulus au 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)
+
+/*
+ * XXX this may not work properly on 64-bit if the register
+ * containing oldval has the high half non-zero for some reason.
+ */
+#define __arch_compare_and_exchange_32_acq(mem, newval, oldval)	\
+({								\
+  unsigned int __tmp;						\
+  __asm __volatile("1:	lwarx	%0,0,%1\n"			\
+		   "	subf.	%0,%2,%0\n"			\
+		   "	bne	2f\n"				\
+		   "	stwcx.	%3,0,%1\n"			\
+		   "	bne-	1b\n"				\
+		   "2:	isync"					\
+		   : "=&r" (__tmp)				\
+		   : "r" (mem), "r" (oldval), "r" (newval)	\
+		   : "cr0", "memory");				\
+  __tmp != 0;							\
+})
+
+#ifdef __powerpc64__
+#define __arch_compare_and_exchange_64_acq(mem, newval, oldval)	\
+({								\
+  unsigned long	__tmp;						\
+  __asm __volatile("1:	ldarx	%0,0,%1\n"			\
+		   "	subf.	%0,%2,%0\n"			\
+		   "	bne	2f\n"				\
+		   "	stdcx.	%3,0,%1\n"			\
+		   "	bne-	1b\n"				\
+		   "2:	isync"					\
+		   : "=&r" (__tmp)				\
+		   : "r" (mem), "r" (oldval), "r" (newval)	\
+		   : "cr0", "memory");				\
+  __tmp != 0;							\
+})
+
+#else /* powerpc32 */
+#define __arch_compare_and_exchange_64_acq(mem, newval, oldval) \
+  (abort (), 0)
+#endif
+
+#define atomic_full_barrier()	__asm("sync" ::: "memory")
+#ifdef __powerpc64__
+#define atomic_read_barrier()	__asm("lwsync" ::: "memory")
+#else
+#define atomic_read_barrier()	__asm("sync" ::: "memory")
+#endif
+#define atomic_write_barrier()	__asm("eieio" ::: "memory")
diff -urN orig/nptl/sysdeps/powerpc/pthread_spin_init.c libc/nptl/sysdeps/powerpc/pthread_spin_init.c
--- orig/nptl/sysdeps/powerpc/pthread_spin_init.c	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/powerpc/pthread_spin_init.c	Wed Mar 05 14:25:16 2003
@@ -0,0 +1,27 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Mackerras <paulus au 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_init (pthread_spinlock_t *lock)
+{
+  *lock = 0;
+  return 0;
+}
diff -urN orig/nptl/sysdeps/powerpc/pthread_spin_lock.c libc/nptl/sysdeps/powerpc/pthread_spin_lock.c
--- orig/nptl/sysdeps/powerpc/pthread_spin_lock.c	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/powerpc/pthread_spin_lock.c	Wed Mar 05 14:41:57 2003
@@ -0,0 +1,44 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Mackerras <paulus au 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 int old;
+
+  asm ("1:	lwarx	%0,0,%1\n"
+       "	cmpwi	0,%0,0\n"
+       "	bne-	2f\n"
+       "	stwcx.	%2,0,%1\n"
+       "	bne-	2f\n"
+       "	isync\n"
+       "	.subsection 1\n"
+       "2:	lwzx	%0,0,%1\n"
+       "	cmpwi	0,%0,0\n"
+       "	bne	2b\n"
+       "	b	1b\n"
+       "	.previous"
+       : "=&r" (__tmp),
+       : "r" (lock), "r" (1)
+       : "cr0", "memory");
+  return 0;
+}
diff -urN orig/nptl/sysdeps/powerpc/pthread_spin_trylock.c libc/nptl/sysdeps/powerpc/pthread_spin_trylock.c
--- orig/nptl/sysdeps/powerpc/pthread_spin_trylock.c	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/powerpc/pthread_spin_trylock.c	Wed Mar 05 14:44:53 2003
@@ -0,0 +1,43 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Mackerras <paulus au 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 int old;
+  int err = EBUSY;
+
+  asm ("1:	lwarx	%0,0,%2\n"
+       "	cmpwi	0,%0,0\n"
+       "	bne	2f\n"
+       "	stwcx.	%3,0,%2\n"
+       "	bne-	1b\n"
+       "	li	%1,0\n"
+       "	isync\n"
+       "2:	"
+       : "=&r" (old), "=&r" (err)
+       : "r" (lock), "r" (1), "1" (err)
+       : "cr0", "memory");
+
+  return err;
+}
diff -urN orig/nptl/sysdeps/powerpc/pthread_spin_unlock.c libc/nptl/sysdeps/powerpc/pthread_spin_unlock.c
--- orig/nptl/sysdeps/powerpc/pthread_spin_unlock.c	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/powerpc/pthread_spin_unlock.c	Wed Mar 05 14:24:57 2003
@@ -0,0 +1,28 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Mackerras <paulus au 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_unlock (pthread_spinlock_t *lock)
+{
+  __asm __volatile ("sync" ::: "memory");
+  *lock = 0;
+  return 0;
+}
diff -urN orig/nptl/sysdeps/powerpc/pthreaddef.h libc/nptl/sysdeps/powerpc/pthreaddef.h
--- orig/nptl/sysdeps/powerpc/pthreaddef.h	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/powerpc/pthreaddef.h	Wed Mar 05 14:46:47 2003
@@ -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	(4 * 1024 * 1024)
+
+/* Required stack pointer alignment at beginning.  The ABI requires 16
+   bytes (for both 32-bit and 64-bit PowerPC).  */
+#define STACK_ALIGN		16
+
+/* Minimal stack size after allocating thread descriptor and guard size.  */
+#define MINIMAL_REST_STACK	4096
+
+/* 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 -urN orig/nptl/sysdeps/powerpc/tcb-offsets.sym libc/nptl/sysdeps/powerpc/tcb-offsets.sym
--- orig/nptl/sysdeps/powerpc/tcb-offsets.sym	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/powerpc/tcb-offsets.sym	Wed Mar 05 16:00:27 2003
@@ -0,0 +1,16 @@
+#include <sysdep.h>
+#include <tls.h>
+
+--
+
+-- This could go into powerpc32/ instead and conditionalize #include of it.
+#ifndef __powerpc64__
+
+-- Abuse tls.h macros to derive offsets relative to the thread register.
+# undef __thread_register
+# define __thread_register	((void *) 0)
+# define thread_offsetof(mem)	((void *) &THREAD_SELF->mem - (void *) 0)
+
+MULTIPLE_THREADS_OFFSET		thread_offsetof (header.data.multiple_threads)
+
+#endif
diff -urN orig/nptl/sysdeps/powerpc/tls.h libc/nptl/sysdeps/powerpc/tls.h
--- orig/nptl/sysdeps/powerpc/tls.h	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/powerpc/tls.h	Thu Mar 06 15:25:36 2003
@@ -0,0 +1,144 @@
+/* Definition for thread-local data handling.  NPTL/PowerPC 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>
+
+/* Type for the dtv.  */
+typedef union dtv
+{
+  size_t counter;
+  void *pointer;
+} dtv_t;
+
+#else /* __ASSEMBLER__ */
+# include <tcb-offsets.h>
+#endif /* __ASSEMBLER__ */
+
+
+/* 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
+
+#ifndef __ASSEMBLER__
+
+/* Get system call information.  */
+# include <sysdep.h>
+
+/* Get the thread descriptor definition.  */
+# include <nptl/descr.h>
+
+/* This layout is actually wholly private and not affected by the ABI.
+   Nor does it overlap the pthread data structure, so we need nothing
+   extra here at all.  */
+typedef struct
+{
+  dtv_t *dtv;
+} tcbhead_t;
+
+/* 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 (tcbhead_t)
+
+/* Alignment requirements for the TCB.  */
+# define TLS_TCB_ALIGN		__alignof__ (tcbhead_t)
+
+/* This is the size we need before TCB.  */
+# define TLS_PRE_TCB_SIZE	sizeof (struct pthread)
+
+/* XXX if __alignof__(struct pthread) > __alignof(tcbhead_t)
+   we could be in trouble.  -- paulus */
+
+# ifndef __powerpc64__
+/* Register r2 (tp) is reserved by the ABI as "thread pointer". */
+register void *__thread_register __asm__("r2");
+# else
+/* Register r13 (tp) is reserved by the ABI as "thread pointer". */
+register void *__thread_register __asm__("r13");
+# endif
+
+/* The following assumes that TP (R2 or R13) points to the end of the
+   TCB + 0x7000 (per the ABI).  This implies that TCB address is
+   TP-(TLS_TCB_SIZE + 0x7000).  As we define TLS_DTV_AT_TP we can
+   assume that the pthread struct is allocated immediately ahead of the
+   TCB.  This implies that the pthread_descr address is
+   TP-(TLS_PRE_TCB_SIZE + TLS_TCB_SIZE + 0x7000).  */
+# define TLS_TCB_OFFSET	0x7000
+
+/* The TP points to the start of the thread blocks.  */
+# define TLS_DTV_AT_TP	1
+
+/* Install the dtv pointer.  The pointer passed is to the element with
+   index -1 which contain the length.  */
+# define INSTALL_DTV(tcbp, dtvp) \
+  ((tcbhead_t *) (tcbp))->dtv = dtvp + 1
+
+/* Install new dtv for current thread.  */
+# define INSTALL_NEW_DTV(dtv) (THREAD_DTV() = (dtv))
+
+/* Return dtv of given thread descriptor.  */
+# define GET_DTV(tcbp)	(((tcbhead_t *) (tcbp))->dtv)
+
+/* 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(tcbp, secondcall) \
+    (__thread_register = (void *) (tcbp) + TLS_TCB_OFFSET + TLS_TCB_SIZE, NULL)
+
+/* Return the address of the dtv for the current thread.  */
+# define THREAD_DTV() \
+     (((tcbhead_t *) (__thread_register - TLS_TCB_OFFSET - TLS_TCB_SIZE))->dtv)
+
+/* Return the thread descriptor for the current thread.  */
+# define THREAD_SELF \
+    ((struct pthread *) (__thread_register \
+			 - TLS_TCB_OFFSET - TLS_TCB_SIZE - TLS_PRE_TCB_SIZE))
+
+/* Read member of the thread descriptor directly.  */
+# define THREAD_GETMEM(descr, member) ((THREAD_SELF)->member)
+
+/* Same as THREAD_GETMEM, but the member offset can be non-constant.  */
+# define THREAD_GETMEM_NC(descr, member, idx) ((THREAD_SELF)->member[idx])
+
+/* Set member of the thread descriptor directly.  */
+# define THREAD_SETMEM(descr, member, value) \
+    (THREAD_SELF)->member = (value)
+
+/* Same as THREAD_SETMEM, but the member offset can be non-constant.  */
+# define THREAD_SETMEM_NC(descr, member, idx, value) \
+    (THREAD_SELF)->member[idx] = (value)
+
+#endif /* __ASSEMBLER__ */
+
+#endif	/* tls.h */
diff -urN orig/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h libc/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
--- orig/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h	Wed Mar 05 14:13:24 2003
@@ -0,0 +1,166 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Mackerras <paulus au 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
+   deliberately not exposed.  */
+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 deliberately not exposed.  */
+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 deliberately not exposed.  */
+typedef union
+{
+  struct
+  {
+    int __lock;
+    int __pad;
+    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 deliberately not exposed.  */
+typedef union
+{
+  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;
+    /* FLAGS must stay at this position in the structure to maintain
+       binary compatibility.  */
+    unsigned int __flags;
+  } __data;
+  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 -urN orig/nptl/sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h libc/nptl/sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h
--- orig/nptl/sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h	Wed Mar 05 14:20:01 2003
@@ -0,0 +1,43 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Mackerras <paulus au 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 -urN orig/nptl/sysdeps/unix/sysv/linux/powerpc/createthread.c libc/nptl/sysdeps/unix/sysv/linux/powerpc/createthread.c
--- orig/nptl/sysdeps/unix/sysv/linux/powerpc/createthread.c	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/createthread.c	Wed Mar 05 16:21:52 2003
@@ -0,0 +1,24 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Mackerras <paulus au 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.  */
+
+/* Value passed to 'clone' for initialization of the thread register.  */
+#define TLS_VALUE ((pd) + 1)
+
+/* Get the real implementation.	 */
+#include <nptl/sysdeps/pthread/createthread.c>
diff -urN orig/nptl/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.h libc/nptl/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.h
--- orig/nptl/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.h	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.h	Wed Mar 05 16:14:09 2003
@@ -0,0 +1,37 @@
+/* System-specific settings for dynamic linker code.  PowerPC 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 -urN orig/nptl/sysdeps/unix/sysv/linux/powerpc/fork.c libc/nptl/sysdeps/unix/sysv/linux/powerpc/fork.c
--- orig/nptl/sysdeps/unix/sysv/linux/powerpc/fork.c	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/fork.c	Fri Mar 07 08:30:57 2003
@@ -0,0 +1,31 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Mackerras <paulus au 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 -urN orig/nptl/sysdeps/unix/sysv/linux/powerpc/jmp-unwind.c libc/nptl/sysdeps/unix/sysv/linux/powerpc/jmp-unwind.c
--- orig/nptl/sysdeps/unix/sysv/linux/powerpc/jmp-unwind.c	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/jmp-unwind.c	Wed Mar 05 16:04:51 2003
@@ -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 char local_var;
+
+  if (fptr != NULL)
+    fptr (env, &local_var);
+}
diff -urN orig/nptl/sysdeps/unix/sysv/linux/powerpc/libc-lowlevellock.c libc/nptl/sysdeps/unix/sysv/linux/powerpc/libc-lowlevellock.c
--- orig/nptl/sysdeps/unix/sysv/linux/powerpc/libc-lowlevellock.c	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/libc-lowlevellock.c	Thu Mar 06 21:42:50 2003
@@ -0,0 +1,21 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Mackerras <paulus au 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 -urN orig/nptl/sysdeps/unix/sysv/linux/powerpc/libc-lowlevelmutex.c libc/nptl/sysdeps/unix/sysv/linux/powerpc/libc-lowlevelmutex.c
--- orig/nptl/sysdeps/unix/sysv/linux/powerpc/libc-lowlevelmutex.c	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/libc-lowlevelmutex.c	Thu Mar 06 21:43:03 2003
@@ -0,0 +1,21 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Mackerras <paulus au 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 -urN orig/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.c libc/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.c
--- orig/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.c	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.c	Fri Mar 07 09:29:08 2003
@@ -0,0 +1,90 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Mackerras <paulus au 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 <sys/time.h>
+
+
+void __lll_lock_wait (int *futex, int val)
+{
+  do {
+    lll_futex_wait (futex, val);
+  } while (__lll_add(futex, -1) != 0);
+
+  *futex = -1;
+}
+hidden_proto (__lll_lock_wait)
+
+
+/* XXX Should not be in libc.so  */
+int lll_unlock_wake_cb (int *futex)
+{
+  __lll_mutex_add(futex, 1);
+  return 0;
+}
+hidden_proto (lll_unlock_wake_cb)
+
+
+/* XXX Should not be in libc.so  */
+int __lll_timedwait_tid (int *tidp, const struct timespec *abstime)
+{
+  int tid;
+  int err = 0;
+
+  if (abstime == NULL || abstime->tv_nsec >= 1000000000)
+    return EINVAL;
+
+  /* Repeat until thread terminated.  */
+  while ((tid = *tidp) != 0) {
+    struct timeval tv;
+    struct timespec rt;
+    int sec, nsec;
+
+    /* Get the current time.  */
+    gettimeofday (&tv, NULL);
+
+    /* Compute relative timeout.  */
+    sec = abstime->tv_sec - tv.tv_sec;
+    nsec = abstime->tv_nsec - tv.tv_usec * 1000;
+    if (nsec < 0) {
+      nsec += 1000000000;
+      --sec;
+    }
+
+    /* Already timed out?  */
+    err = ETIMEDOUT;
+    if (sec < 0)
+      break;
+
+    /* Wait.  */
+    rt.tv_sec = sec;
+    rt.tv_nsec = nsec;
+
+    /* Wait until thread terminates.  */
+    err = lll_futex_timed_wait (tidp, tid, &rt);
+    if (err != 0)
+      break;
+  }
+
+  return err;
+}
+
+hidden_proto (__lll_timedwait_tid)
diff -urN orig/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h libc/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h
--- orig/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h	Fri Mar 07 09:47:49 2003
@@ -0,0 +1,273 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Mackerras <paulus au 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 __NR_futex		221
+#define FUTEX_WAIT		0
+#define FUTEX_WAKE		1
+
+/* Initializer for compatibility lock.	*/
+#define LLL_MUTEX_LOCK_INITIALIZER (0)
+
+#define lll_futex_wait(futexp, val)				\
+  ({								\
+    INTERNAL_SYSCALL_DECL(__err);				\
+    long int __ret;						\
+								\
+    __ret = INTERNAL_SYSCALL(futex, __err, 4,			\
+			     (futexp), FUTEX_WAIT, (val), 0);	\
+    INTERNAL_SYSCALL_ERROR_P(__ret, __err)? -__ret: 0;		\
+  })
+
+#define lll_futex_timed_wait(futexp, val, timespec)			\
+  ({									\
+    INTERNAL_SYSCALL_DECL(__err);					\
+    long int __ret;							\
+									\
+    __ret = INTERNAL_SYSCALL(futex, __err, 4,				\
+			     (futexp), FUTEX_WAIT, (val), (timespec));	\
+    INTERNAL_SYSCALL_ERROR_P(__ret, __err)? -__ret: 0;			\
+  })
+
+#define lll_futex_wake(futexp, nr) 				\
+  ({								\
+    INTERNAL_SYSCALL_DECL(__err);				\
+    long int __ret;						\
+								\
+    __ret = INTERNAL_SYSCALL(futex, __err, 4,			\
+			     (futexp), FUTEX_WAKE, (nr), 0);	\
+    INTERNAL_SYSCALL_ERROR_P(__ret, __err)? -__ret: 0;		\
+  })
+
+/* Set *futex to 1 if it is 0, atomically.  Returns the old value */
+#define __lll_mutex_trylock(futex)				\
+  ({ int __val;							\
+     __asm __volatile ("1:	lwarx	%0,0,%2\n"		\
+		       "	cmpwi	0,%0,0\n"		\
+		       "	bne	2f\n"			\
+		       "	stwcx.	%3,0,%2\n"		\
+		       "	bne-	1b\n"			\
+		       "2:	isync"				\
+		       : "=&r" (__val), "=m" (*futex)		\
+		       : "r" (futex), "r" (1), "1" (*futex)	\
+		       : "cr0");				\
+     __val;							\
+  })
+
+#define lll_mutex_trylock(lock)	__lll_mutex_trylock(&(lock))
+
+/* Add inc to *futex atomically and return the old value. */
+#define __lll_mutex_add(futex, inc)					\
+  ({ int __val, __tmp;							\
+     __asm __volatile ("1:	lwarx	%0,0,%3\n"			\
+		       "	addi	%1,%0,%4\n"			\
+		       "	stwcx.	%1,0,%3\n"			\
+		       "	bne-	1b\n"				\
+		       "	isync"					\
+		       : "=&b" (__val), "=&r" (__tmp), "=m" (*futex)	\
+		       : "r" (futex), "I" (inc), "1" (*futex)		\
+		       : "cr0");					\
+     __val;								\
+  })
+
+extern void __lll_mutex_lock_wait (int *futex, int val) attribute_hidden;
+
+#define lll_mutex_lock(lock)			\
+  (void) ({						\
+    int *__futex = &(lock);			\
+    int __val = __lll_mutex_add(__futex, 1);	\
+    if (__builtin_expect(__val != 0, 0))	\
+      __lll_mutex_lock_wait(__futex, __val);	\
+  })
+
+extern int __lll_mutex_timedlock_wait
+	(int *futex, int val, const struct timespec *) attribute_hidden;
+
+#define lll_mutex_timedlock(lock, abstime)				\
+  ({ int *__futex = &(lock);						\
+     int __val = __lll_mutex_add(__futex, 1);				\
+     if (__builtin_expect(__val != 0, 0))				\
+       __val = __lll_mutex_timedlock_wait(__futex, __val, (abstime));	\
+     __val;								\
+  })
+
+extern void __lll_mutex_unlock_wake (int *futex) attribute_hidden;
+
+#define lll_mutex_unlock(lock)			\
+  (void) ({						\
+    int *__futex = &(lock);			\
+    int __val = __lll_mutex_add(__futex, -1);	\
+    if (__builtin_expect(__val != 1, 0)) {	\
+      *__futex = 0;				\
+      lll_futex_wake(__futex, 1);		\
+    }						\
+  })
+
+#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 */
+
+/* Set *futex to 0 if it is 1, atomically.  Returns the old value */
+#define __lll_trylock(futex)					\
+  ({ int __val;							\
+     __asm __volatile ("1:	lwarx	%0,0,%2\n"		\
+		       "	cmpwi	0,%0,1\n"		\
+		       "	bne	2f\n"			\
+		       "	stwcx.	%3,0,%2\n"		\
+		       "	bne-	1b\n"			\
+		       "2:	isync"				\
+		       : "=&r" (__val), "=m" (*futex)		\
+		       : "r" (futex), "r" (0), "1" (*futex)	\
+		       : "cr0");				\
+     __val;							\
+  })
+
+#define lll_trylock(lock)	__lll_trylock(&(lock))
+
+/* Add inc to *futex atomically and return the new value. */
+#define __lll_add(futex, inc)					\
+  ({ int __val;							\
+     __asm __volatile ("1:	lwarx	%0,0,%2\n"		\
+		       "	addi	%0,%0,%3\n"		\
+		       "	stwcx.	%0,0,%2\n"		\
+		       "	bne-	1b\n"			\
+		       "	isync"				\
+		       : "=&b" (__val), "=m" (*futex)		\
+		       : "r" (futex), "I" (inc), "1" (*futex)	\
+		       : "cr0");				\
+     __val;							\
+  })
+
+extern void __lll_lock_wait (int *, int) attribute_hidden;
+
+#define lll_lock(lock)				\
+  (void) ({						\
+    int *__futex = &(lock);			\
+    int __val = __lll_add(__futex, -1);		\
+    if (__builtin_expect(__val != 0, 0))	\
+      __lll_lock_wait(__futex, __val);		\
+  })
+
+extern void __lll_unlock_wake (int *futex) attribute_hidden;
+
+#define lll_unlock(lock)			\
+  (void) ({						\
+    int *__futex = &(lock);			\
+    int __val = __lll_add(__futex, 1);		\
+    if (__builtin_expect(__val <= 0, 0)) {	\
+      *__futex = 1;				\
+      lll_futex_wake(__futex, 1);		\
+    }						\
+  })
+
+#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.	*/
+#define lll_wait_tid(tid)			\
+  do {						\
+    __typeof(tid) __tid;			\
+    while ((__tid = (tid)) != 0) {		\
+      lll_futex_wait(&(tid), __tid);		\
+    }						\
+  }
+
+extern int __lll_timedwait_tid (int *, const struct timespec *)
+     attribute_hidden;
+
+#define lll_timedwait_tid(tid, abstime)			\
+  ({							\
+    int __res = 0;					\
+    if ((tid) != 0)					\
+      __res = __lll_timedwait_tid(&(tid), (abstime));	\
+    __res;						\
+  })
+
+#define lll_wake_tid(tid) {			\
+  do {						\
+    (tid) = 0;					\
+    lll_futex_wake(&(tid), 0x7fffffff);		\
+  } while (0)
+
+
+/* Decrement *futex if it is > 0, and return the old value */
+#define __lll_dec_if_positive(futex)					\
+  ({ int __val, __tmp;							\
+     __asm __volatile ("1:	lwarx	%0,0,%3\n"			\
+		       "	cmpwi	0,%0,0\n"			\
+		       "	addi	%1,%0,-1\n"			\
+		       "	ble	2f\n"				\
+		       "	stwcx.	%1,0,%3\n"			\
+		       "	bne-	1b\n"				\
+		       "2:	isync"					\
+		       : "=&b" (__val), "=&r" (__tmp), "=m" (*futex)	\
+		       : "r" (futex), "1" (*futex)			\
+		       : "cr0");					\
+     __val;								\
+  })
+
+
+/* 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 -urN orig/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevelmutex.c libc/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevelmutex.c
--- orig/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevelmutex.c	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevelmutex.c	Fri Mar 07 09:02:34 2003
@@ -0,0 +1,72 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Mackerras <paulus au 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_wait (int *futex, int val)
+{
+  do {
+      lll_futex_wait (futex, val+1);
+  } while ((val = __lll_mutex_add(futex, 1)) != 0);
+  *futex = 2;
+}
+hidden_proto (__lll_mutex_lock_wait)
+
+
+int __lll_mutex_timedlock (int *futex, const struct timespec *abstime, int val)
+{
+  int err;
+
+  /* Reject invalid timeouts.  */
+  if (abstime->tv_nsec >= 1000000000)
+    return EINVAL;
+
+  do {
+    struct timeval tv;
+    struct timespec rt;
+    int sec, nsec;
+
+    /* Get the current time.  */
+    gettimeofday (&tv, NULL);
+
+    /* Compute relative timeout.  */
+    sec = abstime->tv_sec - tv.tv_sec;
+    nsec = abstime->tv_nsec - tv.tv_usec * 1000;
+    if (nsec < 0) {
+      nsec += 1000000000;
+      --sec;
+    }
+
+    /* Already timed out?  */
+    err = ETIMEDOUT;
+    if (sec < 0)
+      break;
+
+    /* Wait.  */
+    rt.tv_sec = sec;
+    rt.tv_nsec = nsec;
+    err = lll_futex_timed_wait (futex, val+1, &rt);
+  } while (err == 0 && (val = __lll_mutex_add(futex, 1)) != 0);
+
+  *futex = 2;
+  return err;
+}
+hidden_proto (__lll_mutex_timedlock_wait)
diff -urN orig/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h libc/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h
--- orig/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h	Fri Mar 07 09:06:44 2003
@@ -0,0 +1,100 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Franz Sirl <Franz Sirl-kernel lauterbach 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 <linuxthreads/internals.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)				\
+  .section ".text";							\
+  ENTRY (name)								\
+    SINGLE_THREAD_P;							\
+    bne- .Lpseudo_cancel;						\
+    DO_CALL (SYS_ify (syscall_name));					\
+    PSEUDO_RET;								\
+  .Lpseudo_cancel:							\
+    stwu 1,-48(1);							\
+    mflr 9;								\
+    stw 9,52(1);							\
+    DOCARGS_##args;	/* save syscall args around CENABLE.  */	\
+    CENABLE;								\
+    stw 3,16(1);	/* store CENABLE return value (MASK).  */	\
+    UNDOCARGS_##args;	/* restore syscall args.  */			\
+    DO_CALL (SYS_ify (syscall_name));					\
+    mfcr 0;		/* save CR/R3 around CDISABLE.  */		\
+    stw 3,8(1);								\
+    stw 0,12(1);							\
+    lwz 3,16(1);	/* pass MASK to CDISABLE.  */			\
+    CDISABLE;								\
+    lwz 4,52(1);							\
+    lwz 0,12(1);	/* restore CR/R3. */				\
+    lwz 3,8(1);								\
+    mtlr 4;								\
+    mtcr 0;								\
+    addi 1,1,48;
+
+# define DOCARGS_0
+# define UNDOCARGS_0
+
+# define DOCARGS_1	stw 3,20(1); DOCARGS_0
+# define UNDOCARGS_1	lwz 3,20(1); UNDOCARGS_0
+
+# define DOCARGS_2	stw 4,24(1); DOCARGS_1
+# define UNDOCARGS_2	lwz 4,24(1); UNDOCARGS_1
+
+# define DOCARGS_3	stw 5,28(1); DOCARGS_2
+# define UNDOCARGS_3	lwz 5,28(1); UNDOCARGS_2
+
+# define DOCARGS_4	stw 6,32(1); DOCARGS_3
+# define UNDOCARGS_4	lwz 6,32(1); UNDOCARGS_3
+
+# define DOCARGS_5	stw 7,36(1); DOCARGS_4
+# define UNDOCARGS_5	lwz 7,36(1); UNDOCARGS_4
+
+# define DOCARGS_6	stw 8,40(1); DOCARGS_5
+# define UNDOCARGS_6	lwz 8,40(1); UNDOCARGS_5
+
+# ifdef IS_IN_libpthread
+#  define CENABLE	bl JUMPTARGET(__pthread_enable_asynccancel)
+#  define CDISABLE	bl JUMPTARGET(__pthread_disable_asynccancel)
+# else
+#  define CENABLE	bl JUMPTARGET(__libc_enable_asynccancel)
+#  define CDISABLE	bl JUMPTARGET(__libc_disable_asynccancel)
+# endif
+
+# ifndef __ASSEMBLER__
+#  define SINGLE_THREAD_P						\
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF, p_multiple_threads) == 0, 1)
+# else
+#  define SINGLE_THREAD_P						\
+  lwz 10,MULTIPLE_THREADS_OFFSET(2);					\
+  cmpwi 10,0
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
diff -urN orig/nptl/sysdeps/unix/sysv/linux/powerpc/pt-vfork.S libc/nptl/sysdeps/unix/sysv/linux/powerpc/pt-vfork.S
--- orig/nptl/sysdeps/unix/sysv/linux/powerpc/pt-vfork.S	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/pt-vfork.S	Fri Mar 07 09:14:43 2003
@@ -0,0 +1,35 @@
+/* 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 <sysdep-cancel.h>
+#define _ERRNO_H	1
+#include <bits/errno.h>
+#include <kernel-features.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_CALL (SYS_ify (vfork));
+	PSEUDO_RET
+
+PSEUDO_END (__vfork)
+
+weak_alias (__vfork, vfork)
diff -urN orig/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c libc/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c
--- orig/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c	Fri Mar 07 08:21:09 2003
@@ -0,0 +1,98 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Mackerras <paulus au 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 (pthread_once_t *once_control, void (*init_routine) (void))
+{
+  for (;;) {
+    int oldval;
+    int newval;
+    int tmp;
+
+    /* Pseudo code:
+       newval = __fork_generation | 1;
+       oldval = *once_control;
+       if ((oldval & 2) == 0) {
+	 *once_control = newval;
+       }
+       Do this atomically.
+    */
+    newval = __fork_generation | 1;
+    __asm __volatile ( "1:	lwarx	%0,0,%3\n"
+		       "	andi.	%1,%0,2\n"
+		       "	bne	2f\n"
+		       "	stwcx.	%4,0,%3\n"
+		       "2:	isync"
+		       : "=&r" (oldval), "=&r" (tmp), "=m" (*once_control)
+		       : "r" (once_control), "r" (newval), "m" (*once_control)
+		       : "cr0");
+
+    /* Check if the initializer has already been done.  */
+    if ((oldval & 2) != 0)
+      return 0;
+
+    /* Check if another thread already runs the initializer.	*/
+    if ((oldval & 1) == 0)
+      break;
+
+    /* Check whether the initializer execution was interrupted by a fork.  */
+    if (oldval != newval)
+      break;
+
+    /* Same generation, some other thread was faster. Wait.  */
+    lll_futex_wait (once_control, oldval);
+  }
+
+
+  /* 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 to take the bottom 2 bits from 01 to 10.  */
+  __lll_add(once_control, 1);
+
+  /* Wake up all other threads.  */
+  lll_futex_wake (once_control, INT_MAX);
+
+  return 0;
+}
+weak_alias (__pthread_once, pthread_once)
+strong_alias (__pthread_once, __pthread_once_internal)
diff -urN orig/nptl/sysdeps/unix/sysv/linux/powerpc/sem_post.c libc/nptl/sysdeps/unix/sysv/linux/powerpc/sem_post.c
--- orig/nptl/sysdeps/unix/sysv/linux/powerpc/sem_post.c	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/sem_post.c	Thu Mar 06 22:51:11 2003
@@ -0,0 +1,44 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Mackerras <paulus au 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 <internaltypes.h>
+#include <semaphore.h>
+#include <lowlevellock.h>
+
+#include <shlib-compat.h>
+
+int __new_sem_post (sem_t *sem)
+{
+  int *futex = (int *) sem;
+  int err, nr;
+
+  nr = __lll_add(futex, 1);
+  err = lll_futex_wake(futex, nr);
+  if (err == 0)
+    return 0;
+  __set_errno(-err);
+  return -1;
+}
+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 -urN orig/nptl/sysdeps/unix/sysv/linux/powerpc/sem_timedwait.c libc/nptl/sysdeps/unix/sysv/linux/powerpc/sem_timedwait.c
--- orig/nptl/sysdeps/unix/sysv/linux/powerpc/sem_timedwait.c	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/sem_timedwait.c	Thu Mar 06 22:56:43 2003
@@ -0,0 +1,81 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Mackerras <paulus au 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 <internaltypes.h>
+#include <semaphore.h>
+#include <lowlevellock.h>
+
+#include <shlib-compat.h>
+
+
+int sem_timedwait (sem_t *sem, const struct timespec *abstime)
+{
+  int *futex = (int *) sem;
+  int val;
+  int err;
+
+  if (*futex > 0) {
+    val = __lll_dec_if_positive(futex);
+    if (val > 0)
+      return 0;
+  }
+
+  err = -EINVAL;
+  if (abstime->tv_nsec >= 1000000000)
+    goto error_return;
+
+  do {
+    struct timeval tv;
+    struct timespec rt;
+    int sec, nsec;
+
+    /* Get the current time.  */
+    gettimeofday(&tv, NULL);
+
+    /* Compute relative timeout.  */
+    sec = abstime->tv_sec - tv.tv_sec;
+    nsec = abstime->tv_nsec - tv.tv_usec * 1000;
+    if (nsec < 0) {
+      nsec += 1000000000;
+      --tv_sec;
+    }
+
+    /* Already timed out?  */
+    err = -ETIMEDOUT;
+    if (sec < 0)
+      goto error_return;
+
+    /* Do wait.  */
+    rt.tv_sec = sec;
+    rt.tv_nsec = nsec;
+    err = lll_futex_timed_wait (futex, 0, &rt);
+    if (err != 0 && err != -EWOULDBLOCK)
+      goto error_return;
+
+    val = __lll_dec_if_positive(futex);
+  } while (val <= 0);
+
+  return 0;
+
+ error_return:
+  __set_errno(-err);
+  return -1;
+}
diff -urN orig/nptl/sysdeps/unix/sysv/linux/powerpc/sem_trywait.c libc/nptl/sysdeps/unix/sysv/linux/powerpc/sem_trywait.c
--- orig/nptl/sysdeps/unix/sysv/linux/powerpc/sem_trywait.c	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/sem_trywait.c	Thu Mar 06 22:54:29 2003
@@ -0,0 +1,47 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Mackerras <paulus au 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 <internaltypes.h>
+#include <semaphore.h>
+#include <lowlevellock.h>
+
+#include <shlib-compat.h>
+
+
+int __new_sem_trywait (sem_t *sem)
+{
+  int *futex = (int *) sem;
+  int val;
+
+  if (*futex > 0) {
+    val = __lll_dec_if_positive(futex);
+    if (val > 0)
+      return 0;
+  }
+
+  __set_errno (EAGAIN);
+  return -1;
+}
+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 -urN orig/nptl/sysdeps/unix/sysv/linux/powerpc/sem_wait.c libc/nptl/sysdeps/unix/sysv/linux/powerpc/sem_wait.c
--- orig/nptl/sysdeps/unix/sysv/linux/powerpc/sem_wait.c	Thu Jan 01 10:00:00 1970
+++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/sem_wait.c	Thu Mar 06 22:58:38 2003
@@ -0,0 +1,53 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Mackerras <paulus au 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 <internaltypes.h>
+#include <semaphore.h>
+#include <lowlevellock.h>
+
+#include <shlib-compat.h>
+
+
+int __new_sem_wait (sem_t *sem)
+{
+  int *futex = (int *) sem;
+  int val;
+  int err;
+
+  do {
+    if (*futex > 0) {
+      val = __lll_dec_if_positive(futex);
+      if (val > 0)
+	return 0;
+    }
+
+    err = lll_futex_wait(futex, 0);
+  } while (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





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]