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

Re: First cut of PowerPC support in NPTL



On Sat, Mar 08, 2003 at 11:04:19AM +1100, Ian Wienand wrote:
> well that solves that one.
> 
> yes you are correct, I forgot the " " around the $@ in my gcc wrapper
> script.  

FYI Here is my current IA-64 NPTL patch.
Some NPTL tests already pass, bu some oops the kernel (I was using
2.5.60+davidm's patch), so that needs to be fixed first before further
progress can be made.

--- libc/sysdeps/unix/sysv/linux/ia64/sysdep.h.jj	2003-01-13 07:57:45.000000000 -0500
+++ libc/sysdeps/unix/sysv/linux/ia64/sysdep.h	2003-03-07 09:46:16.000000000 -0500
@@ -176,6 +176,9 @@
 #define LOAD_ARGS_5(out0, out1, out2, out3, out4)	\
   register long _out4 asm ("out4") = (long) (out4);	\
   LOAD_ARGS_4 (out0, out1, out2, out3)
+#define LOAD_ARGS_6(out0, out1, out2, out3, out4, out5)	\
+  register long _out5 asm ("out5") = (long) (out5);	\
+  LOAD_ARGS_5 (out0, out1, out2, out3, out4)
 
 #define ASM_ARGS_0
 #define ASM_ARGS_1      ASM_ARGS_0, "r" (_out0)
@@ -183,13 +186,15 @@
 #define ASM_ARGS_3      ASM_ARGS_2, "r" (_out2)
 #define ASM_ARGS_4      ASM_ARGS_3, "r" (_out3)
 #define ASM_ARGS_5      ASM_ARGS_4, "r" (_out4)
+#define ASM_ARGS_6	ASM_ARGS_5, "r" (_out5)
 
 #define ASM_CLOBBERS_0	ASM_CLOBBERS_1, "out0"
 #define ASM_CLOBBERS_1	ASM_CLOBBERS_2, "out1"
 #define ASM_CLOBBERS_2	ASM_CLOBBERS_3, "out2"
 #define ASM_CLOBBERS_3	ASM_CLOBBERS_4, "out3"
 #define ASM_CLOBBERS_4	ASM_CLOBBERS_5, "out4"
-#define ASM_CLOBBERS_5	, "out5", "out6", "out7",			\
+#define ASM_CLOBBERS_5	ASM_CLOBBERS_6, "out5"
+#define ASM_CLOBBERS_6	, "out6", "out7",				\
   /* Non-stacked integer registers, minus r8, r10, r15.  */		\
   "r2", "r3", "r9", "r11", "r12", "r13", "r14", "r16", "r17", "r18",	\
   "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27",	\
--- libc/sysdeps/unix/sysv/linux/ia64/clone2.S.jj	2003-03-06 12:26:24.000000000 -0500
+++ libc/sysdeps/unix/sysv/linux/ia64/clone2.S	2003-03-07 19:42:25.000000000 -0500
@@ -23,7 +23,7 @@
 
 /* int  __clone2(int (*fn) (void *arg), void *child_stack_base, 	*/
 /* 	         size_t child_stack_size, int flags, void *arg,		*/
-/*	         pid_t *child_tid, pid_t *parent_tid, void *tls) */
+/*	         pid_t *parent_tid, void *tls, pid_t *child_tid)	*/
 
 ENTRY(__clone2)
 	alloc r2=ar.pfs,8,2,6,0
@@ -42,9 +42,9 @@ ENTRY(__clone2)
 	mov out0=in3		/* Flags are first syscall argument.	*/
 	mov out1=in1		/* Stack address.			*/
 	mov out2=in2		/* Stack size.				*/
-	mov out3=in5		/* Child TID Pointer			*/
-	mov out4=in6		/* Parent TID Pointer			*/
- 	mov out5=in7		/* TLS pointer				*/
+	mov out3=in7		/* Child TID Pointer			*/
+	mov out4=in5		/* Parent TID Pointer			*/
+ 	mov out5=in6		/* TLS pointer				*/
         DO_CALL (SYS_ify (clone2))
         cmp.eq p6,p0=-1,r10
 	;;
--- libc/sysdeps/unix/sysv/linux/i386/clone.S.jj	2002-12-10 09:09:30.000000000 -0500
+++ libc/sysdeps/unix/sysv/linux/i386/clone.S	2003-03-07 19:39:30.000000000 -0500
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1997,98,99,2000,02 Free Software Foundation, Inc.
+/* Copyright (C) 1996,1997,98,99,2000,02,03 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson (rth tamu edu)
 
@@ -28,7 +28,7 @@
 #include <bp-asm.h>
 
 /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
-	     pid_t *tid, struct user_desc *tls); */
+	     pid_t *ptid, struct user_desc *tls, pid_t *ctid); */
 
 #define PARMS	LINKAGE		/* no space for saved regs */
 #define FUNC	PARMS
--- libc/nptl/sysdeps/pthread/createthread.c.jj	2003-03-05 14:43:34.000000000 -0500
+++ libc/nptl/sysdeps/pthread/createthread.c	2003-03-07 17:45:10.000000000 -0500
@@ -34,6 +34,10 @@
 # define TLS_VALUE pd
 #endif
 
+#ifndef ARCH_CLONE
+# define ARCH_CLONE __clone
+#endif
+
 
 static int
 create_thread (struct pthread *pd, STACK_VARIABLES_PARMS)
@@ -42,7 +46,9 @@ create_thread (struct pthread *pd, STACK
   PREPARE_CREATE;
 #endif
 
+#ifdef TLS_TCB_AT_TP
   assert (pd->header.data.tcb != NULL);
+#endif
 
 
   if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, report_events), 0))
@@ -62,11 +68,11 @@ create_thread (struct pthread *pd, STACK
 	  lll_lock (pd->lock);
 
 	  /* Create the thread.  */
-	  if (__clone (start_thread_debug, STACK_VARIABLES_ARGS,
-		       CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
-		       CLONE_SETTLS | CLONE_PARENT_SETTID |
-		       CLONE_CHILD_CLEARTID | CLONE_DETACHED | 0,
-		       pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
+	  if (ARCH_CLONE (start_thread_debug, STACK_VARIABLES_ARGS,
+			  CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
+			  CLONE_SETTLS | CLONE_PARENT_SETTID |
+			  CLONE_CHILD_CLEARTID | CLONE_DETACHED | 0,
+			  pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
 	    /* Failed.  */
 	    return errno;
 
@@ -132,10 +138,10 @@ create_thread (struct pthread *pd, STACK
 
      The termination signal is chosen to be zero which means no signal
      is sent.  */
-  if (__clone (start_thread, STACK_VARIABLES_ARGS,
-	       CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
-	       CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
-	       CLONE_DETACHED | 0, pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
+  if (ARCH_CLONE (start_thread, STACK_VARIABLES_ARGS,
+		  CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
+		  CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
+		  CLONE_DETACHED | 0, pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
     /* Failed.  */
     return errno;
 
--- libc/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h.jj	2003-03-07 13:06:11.000000000 -0500
+++ libc/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h	2003-03-06 16:19:20.000000000 -0500
@@ -0,0 +1,153 @@
+/* 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.  */
+
+#ifndef _BITS_PTHREADTYPES_H
+#define _BITS_PTHREADTYPES_H	1
+
+#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
+
+
+/* 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
+{
+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;
+  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 */
--- libc/nptl/sysdeps/unix/sysv/linux/ia64/bits/semaphore.h.jj	2003-03-07 13:06:14.000000000 -0500
+++ libc/nptl/sysdeps/unix/sysv/linux/ia64/bits/semaphore.h	2003-03-06 16:22:52.000000000 -0500
@@ -0,0 +1,39 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper redhat com>, 2002.
+
+   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
+
+
+#define __SIZEOF_SEM_T	32
+
+
+/* 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;
--- libc/nptl/sysdeps/unix/sysv/linux/ia64/fork.c.jj	2003-03-07 13:06:30.000000000 -0500
+++ libc/nptl/sysdeps/unix/sysv/linux/ia64/fork.c	2003-03-06 16:55:07.000000000 -0500
@@ -0,0 +1,31 @@
+/* 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 <sched.h>
+#include <signal.h>
+#include <sysdep.h>
+#include <tls.h>
+
+
+#define ARCH_FORK() \
+  INLINE_SYSCALL (clone2, 6,						      \
+		  CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD,	      \
+		  NULL, 0, &THREAD_SELF->tid, NULL, NULL)
+
+#include "../fork.c"
--- libc/nptl/sysdeps/unix/sysv/linux/ia64/createthread.c.jj	2003-03-07 13:06:30.000000000 -0500
+++ libc/nptl/sysdeps/unix/sysv/linux/ia64/createthread.c	2003-03-07 17:03:22.000000000 -0500
@@ -0,0 +1,26 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub redhat 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 + 1)
+
+#define ARCH_CLONE __clone2
+
+/* Get the real implementation.	 */
+#include <nptl/sysdeps/pthread/createthread.c>
--- libc/nptl/sysdeps/unix/sysv/linux/ia64/libc-lowlevellock.c.jj	2003-03-07 13:06:30.000000000 -0500
+++ libc/nptl/sysdeps/unix/sysv/linux/ia64/libc-lowlevellock.c	2003-03-07 05:37:52.000000000 -0500
@@ -0,0 +1,19 @@
+/* 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.  */
+
+/* Not needed.  lll_mutex_* implementation is the same as lll_*.  */
--- libc/nptl/sysdeps/unix/sysv/linux/ia64/libc-lowlevelmutex.c.jj	2003-03-07 13:06:30.000000000 -0500
+++ libc/nptl/sysdeps/unix/sysv/linux/ia64/libc-lowlevelmutex.c	2003-03-07 05:38:12.000000000 -0500
@@ -0,0 +1,21 @@
+/* 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.  */
+
+/* No difference to lowlevelmutex.c  */
+#include "lowlevelmutex.c"
--- libc/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.c.jj	2003-03-07 13:06:30.000000000 -0500
+++ libc/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.c	2003-03-07 10:41:09.000000000 -0500
@@ -0,0 +1,85 @@
+/* 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 <errno.h>
+#include <sysdep.h>
+#include <lowlevellock.h>
+#include <sys/time.h>
+
+
+int
+lll_unlock_wake_cb (futex)
+     int *futex;
+{
+  int oldval;
+  int val = *futex;
+    
+  do
+    oldval = val;
+  while ((val = lll_compare_and_swap (futex, oldval, 0)) != oldval);
+  if (oldval > 1)
+    lll_futex_wake (futex, 1);
+  return 0;
+}
+hidden_proto (lll_unlock_wake_cb)
+
+
+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)
--- libc/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h.jj	2003-03-07 13:06:30.000000000 -0500
+++ libc/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h	2003-03-07 13:47:15.000000000 -0500
@@ -0,0 +1,248 @@
+/* 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.  */
+
+#ifndef _LOWLEVELLOCK_H
+#define _LOWLEVELLOCK_H	1
+
+#include <time.h>
+#include <sys/param.h>
+#include <bits/pthreadtypes.h>
+#include <ia64intrin.h>
+
+#define SYS_futex		1230
+#define FUTEX_WAIT		0
+#define FUTEX_WAKE		1
+
+/* Initializer for compatibility lock.	*/
+#define LLL_MUTEX_LOCK_INITIALIZER (0)
+
+#define lll_futex_clobbers \
+  "out4", "out5", "out6", "out7",					      \
+  /* Non-stacked integer registers, minus r8, r15.  */			      \
+  "r2", "r3", "r9", "r10", "r11", "r12", "r13", "r14", "r16", "r17", "r18",   \
+  "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27",	      \
+  "r28", "r29", "r30", "r31",						      \
+  /* Predicate registers.  */						      \
+  "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15",	      \
+  /* Non-rotating fp registers.  */					      \
+  "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",	      \
+  /* Branch registers.  */						      \
+  "b6", "b7",								      \
+  "memory"
+
+#define lll_futex_wait(futex, val) \
+  ({									      \
+     register unsigned long int __o0 asm ("out0")			      \
+       = (unsigned long int) (futex);					      \
+     register unsigned long int __o1 asm ("out1") = FUTEX_WAIT;		      \
+     register unsigned long int __o2 asm ("out2") = (unsigned long int) (val);\
+     register unsigned long int __o3 asm ("out3") = 0ul;		      \
+     register unsigned long int __r8 asm ("r8");			      \
+     register unsigned long int __r15 asm ("r15") = SYS_futex;		      \
+									      \
+    __asm __volatile ("break %2;;"					      \
+		      : "=r" (__r8), "=r" (__r15)			      \
+		      : "i" (0x100000), "1" (__r15), "r" (__o0), "r" (__o1),  \
+			"r" (__o2), "r" (__o3)				      \
+		      : lll_futex_clobbers);				      \
+    __r8;								      \
+  })
+
+
+#define lll_futex_timed_wait(futex, val, timespec) \
+  ({									      \
+     register unsigned long int __o0 asm ("out0")			      \
+       = (unsigned long int) (futex);					      \
+     register unsigned long int __o1 asm ("out1") = FUTEX_WAIT;		      \
+     register unsigned long int __o2 asm ("out2") = (unsigned long int) (val);\
+     register unsigned long int __o3 asm ("out3")			      \
+       = (unsigned long int) (timespec);				      \
+     register unsigned long int __r8 asm ("r8");			      \
+     register unsigned long int __r15 asm ("r15") = SYS_futex;		      \
+									      \
+    __asm __volatile ("break %2;;"					      \
+		      : "=r" (__r8), "=r" (__r15)			      \
+		      : "i" (0x100000), "1" (__r15), "r" (__o0), "r" (__o1),  \
+			"r" (__o2), "r" (__o3)				      \
+		      : lll_futex_clobbers);				      \
+    __r8;								      \
+  })
+
+
+#define lll_futex_wake(futex, nr) \
+  ({									      \
+     register unsigned long int __o0 asm ("out0")			      \
+       = (unsigned long int) (futex);					      \
+     register unsigned long int __o1 asm ("out1") = FUTEX_WAKE;		      \
+     register unsigned long int __o2 asm ("out2") = (unsigned long int) (nr); \
+     register unsigned long int __r8 asm ("r8");			      \
+     register unsigned long int __r15 asm ("r15") = SYS_futex;		      \
+									      \
+    __asm __volatile ("break %2;;"					      \
+		      : "=r" (__r8), "=r" (__r15)			      \
+		      : "i" (0x100000), "1" (__r15), "r" (__o0), "r" (__o1),  \
+			"r" (__o2)					      \
+		      : "out3", lll_futex_clobbers);			      \
+    __r8;								      \
+  })
+
+#define lll_compare_and_swap(futex, oldval, newval) \
+  __sync_val_compare_and_swap_si ((futex), (oldval), (newval))
+
+static inline int
+__attribute__ ((always_inline))
+__lll_mutex_trylock (int *futex)
+{
+  return lll_compare_and_swap (futex, 0, 1) != 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 val = *futex;
+
+  do
+    oldval = val;
+  while ((val = lll_compare_and_swap (futex, oldval, oldval + 1)) != oldval);
+  if (oldval > 0)
+    ___lll_mutex_lock (futex, oldval + 1);
+}
+#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, const struct timespec *abstime)
+{
+  int oldval;
+  int val = *futex;
+  int result = 0;
+
+  do
+    oldval = val;
+  while ((val = lll_compare_and_swap (futex, oldval, oldval + 1)) != oldval);
+  if (oldval > 0)
+    result = ___lll_mutex_timedlock (futex, abstime, oldval + 1);
+
+  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 val = *futex;
+
+  do
+    oldval = val;
+  while ((val = lll_compare_and_swap (futex, oldval, 0)) != oldval);
+  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.  We can use the lll_mutex_*.  */
+
+/* Type for lock object.  */
+typedef int lll_lock_t;
+
+extern int lll_unlock_wake_cb (int *__futex) attribute_hidden;
+
+/* Initializers for lock.  */
+#define LLL_LOCK_INITIALIZER		(0)
+#define LLL_LOCK_INITIALIZER_LOCKED	(1)
+
+#define lll_trylock(futex)	lll_mutex_trylock (futex)
+#define lll_lock(futex)		lll_mutex_lock (futex)
+#define lll_unlock(futex)	lll_mutex_unlock (futex)
+#define lll_islocked(futex)	lll_mutex_islocked (futex)
+
+
+/* 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)
+
+
+/* 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 */
--- libc/nptl/sysdeps/unix/sysv/linux/ia64/lowlevelmutex.c.jj	2003-03-07 13:06:30.000000000 -0500
+++ libc/nptl/sysdeps/unix/sysv/linux/ia64/lowlevelmutex.c	2003-03-07 10:59:11.000000000 -0500
@@ -0,0 +1,100 @@
+/* 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 <errno.h>
+#include <sysdep.h>
+#include <lowlevellock.h>
+#include <sys/time.h>
+
+
+void
+___lll_mutex_lock (futex, newval)
+     int *futex;
+     int newval;
+{
+  int oldval, val;
+
+  do
+    {
+      lll_futex_wait (futex, newval);
+      val = *futex;
+      do
+        oldval = val;
+      while ((val = lll_compare_and_swap (futex, oldval, oldval + 1))
+	     != oldval);
+      newval = val + 1;
+    }
+  while (val != 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, val;
+  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;
+
+      val = *futex;
+      do
+        oldval = val;
+      while ((val = lll_compare_and_swap (futex, oldval, oldval + 1))
+	     != oldval);
+      newval = val + 1;
+    }
+  while (val != 0);
+
+  *futex = 2;
+
+  return 0;
+}
+hidden_proto (___lll_mutex_timedlock)
--- libc/nptl/sysdeps/unix/sysv/linux/ia64/lowlevelsem.h.jj	2003-03-07 13:06:30.000000000 -0500
+++ libc/nptl/sysdeps/unix/sysv/linux/ia64/lowlevelsem.h	2003-03-07 07:08:32.000000000 -0500
@@ -0,0 +1,79 @@
+/* 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.  */
+
+#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, val;
+
+  val = *(int *) sem;
+  do
+    {
+      if (__builtin_expect (val == 0, 0))
+	{
+	  /* Do wait.  */
+	  int err = lll_futex_wait ((int *) sem, 0);
+
+	  /* Handle EINTR.  */
+	  if (err != 0 && err != -EWOULDBLOCK)
+	    return -err;
+
+	  val = *(int *) sem;
+	}
+      oldval = val;
+    }
+  while ((val = lll_compare_and_swap ((int *) sem, oldval, oldval - 1))
+	 != oldval);
+  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, val;
+
+  val = *(int *) sem;
+  do
+    oldval = val;
+  while ((val = lll_compare_and_swap ((int *) sem, oldval, oldval + 1))
+	 != oldval);
+  lll_futex_wake ((int *) sem, oldval + 1);
+}
+
+#endif	/* lowlevelsem.h */
--- libc/nptl/sysdeps/unix/sysv/linux/ia64/pt-initfini.c.jj	2003-03-07 13:06:30.000000000 -0500
+++ libc/nptl/sysdeps/unix/sysv/linux/ia64/pt-initfini.c	2003-03-07 07:01:04.000000000 -0500
@@ -0,0 +1,108 @@
+/* Special .init and .fini section support for ia64. NPTL version.
+   Copyright (C) 2000, 2001, 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.
+
+   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\
+\n\
+#include \"defs.h\"\n\
+\n\
+/* HEADER_ENDS*/\n\
+\n\
+/* _init_PROLOG_BEGINS*/\n\
+	.section .init\n\
+	.align 16\n\
+	.global _init#\n\
+	.proc _init#\n\
+_init:\n\
+	alloc r34 = ar.pfs, 0, 3, 0, 0\n\
+	mov r32 = r12\n\
+	mov r33 = b0\n\
+	adds r12 = -16, r12\n\
+	;;\n\
+/* we could use r35 to save gp, but we use the stack since that's what\n\
+ * all the other init routines will do --davidm 00/04/05 */\n\
+	st8 [r12] = gp, -16\n\
+	br.call.sptk.many b0 = __pthread_initialize_minimal_internal# ;;\n\
+	;;\n\
+	adds r12 = 16, r12\n\
+	;;\n\
+	ld8 gp = [r12]\n\
+	;;\n\
+	.align 16\n\
+	.endp _init#\n\
+\n\
+/* _init_PROLOG_ENDS*/\n\
+\n\
+/* _init_EPILOG_BEGINS*/\n\
+	.section .init\n\
+	.regstk 0,2,0,0\n\
+	mov r12 = r32\n\
+	mov ar.pfs = r34\n\
+	mov b0 = r33\n\
+	br.ret.sptk.many b0\n\
+	.endp _init#\n\
+/* _init_EPILOG_ENDS*/\n\
+\n\
+/* _fini_PROLOG_BEGINS*/\n\
+	.section .fini\n\
+	.align 16\n\
+	.global _fini#\n\
+	.proc _fini#\n\
+_fini:\n\
+	alloc r34 = ar.pfs, 0, 3, 0, 0\n\
+	mov r32 = r12\n\
+	mov r33 = b0\n\
+	adds r12 = -16, r12\n\
+	;;\n\
+	.align 16\n\
+	.endp _fini#\n\
+\n\
+/* _fini_PROLOG_ENDS*/\n\
+\n\
+/* _fini_EPILOG_BEGINS*/\n\
+	.section .fini\n\
+	mov r12 = r32\n\
+	mov ar.pfs = r34\n\
+	mov b0 = r33\n\
+	br.ret.sptk.many b0\n\
+	.endp _fini#\n\
+\n\
+/* _fini_EPILOG_ENDS*/\n\
+\n\
+/* TRAILER_BEGINS*/\n\
+	.weak	__gmon_start__#\n\
+");
--- libc/nptl/sysdeps/unix/sysv/linux/ia64/pt-vfork.S.jj	2003-03-07 13:06:30.000000000 -0500
+++ libc/nptl/sysdeps/unix/sysv/linux/ia64/pt-vfork.S	2003-03-07 06:59:40.000000000 -0500
@@ -0,0 +1,44 @@
+/* Copyright (C) 2000, 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.  */
+
+
+#include <sysdep.h>
+#define _SIGNAL_H
+#include <bits/signum.h>
+
+/* The following are defined in linux/sched.h, which unfortunately	*/
+/* is not safe for inclusion in an assembly file.			*/
+#define CLONE_VM        0x00000100      /* set if VM shared between processes */
+#define CLONE_VFORK     0x00004000      /* set if the parent wants the child to wake it up on mm_release */
+
+/* pid_t vfork(void); */
+/* Implemented as __clone_syscall(CLONE_VFORK | CLONE_VM | SIGCHLD, 0)	*/
+
+ENTRY(__vfork)
+	alloc r2=ar.pfs,0,0,2,0
+	mov out0=CLONE_VM+CLONE_VFORK+SIGCHLD
+	mov out1=0		/* Standard sp value.			*/
+	;;
+	DO_CALL (SYS_ify (clone))
+	cmp.eq p6,p0=-1,r10
+	;;
+(p6)	br.cond.spnt.few __syscall_error
+	ret
+PSEUDO_END(__vfork)
+
+weak_alias (__vfork, vfork)
--- libc/nptl/sysdeps/unix/sysv/linux/ia64/pthread_once.c.jj	2003-03-07 13:06:30.000000000 -0500
+++ libc/nptl/sysdeps/unix/sysv/linux/ia64/pthread_once.c	2003-03-07 10:36:28.000000000 -0500
@@ -0,0 +1,97 @@
+/* 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 "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, val, newval;
+
+      val = *once_control;
+      do
+	{
+	  /* Check if the initialized has already been done.  */
+	  if ((val & 2) != 0)
+	    return 0;
+
+	  oldval = val;
+	  newval = (oldval & 3) | __fork_generation | 1;
+	}
+      while ((val = lll_compare_and_swap (once_control, oldval, newval))
+	     != oldval);
+      
+      /* 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.  */
+      val = *once_control;
+      do
+	oldval = val;
+      while ((val = lll_compare_and_swap (once_control, oldval, oldval + 1))
+	     != oldval);
+
+      /* 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)
--- libc/nptl/sysdeps/unix/sysv/linux/ia64/sem_post.c.jj	2003-03-07 13:06:30.000000000 -0500
+++ libc/nptl/sysdeps/unix/sysv/linux/ia64/sem_post.c	2003-03-07 06:14:34.000000000 -0500
@@ -0,0 +1,51 @@
+/* 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 <errno.h>
+#include <sysdep.h>
+#include <lowlevelsem.h>
+#include <internaltypes.h>
+
+#include <shlib-compat.h>
+
+
+int
+__new_sem_post (sem_t *sem)
+{
+  int oldval, val;
+  int err;
+
+  val = *(int *) sem;
+  do
+    oldval = val;
+  while ((val = lll_compare_and_swap ((int *) sem, oldval, oldval + 1))
+	 != oldval);
+  err = lll_futex_wake ((int *) sem, oldval + 1);
+  if (err < 0)
+    {
+      __set_errno (-err);
+      return -1;
+    }
+  return 0;
+}
+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
--- libc/nptl/sysdeps/unix/sysv/linux/ia64/sem_timedwait.c.jj	2003-03-07 13:06:30.000000000 -0500
+++ libc/nptl/sysdeps/unix/sysv/linux/ia64/sem_timedwait.c	2003-03-07 06:45:36.000000000 -0500
@@ -0,0 +1,91 @@
+/* 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 <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, val;
+
+  val = *(int *) sem;
+  do
+    {
+      while (__builtin_expect (val == 0, 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;
+	    }
+
+	  val = *(int *) sem;
+	}
+      oldval = val;
+    }
+  while ((val = lll_compare_and_swap ((int *) sem, oldval, oldval - 1))
+	 != oldval);
+  return 0;
+}
--- libc/nptl/sysdeps/unix/sysv/linux/ia64/sem_trywait.c.jj	2003-03-07 13:06:30.000000000 -0500
+++ libc/nptl/sysdeps/unix/sysv/linux/ia64/sem_trywait.c	2003-03-07 06:37:48.000000000 -0500
@@ -0,0 +1,50 @@
+/* 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 <errno.h>
+#include <sysdep.h>
+#include <lowlevelsem.h>
+#include <internaltypes.h>
+
+#include <shlib-compat.h>
+
+
+int
+__new_sem_trywait (sem_t *sem)
+{
+  int oldval, val = *(int *) sem;
+
+  do
+    {
+      if (__builtin_expect (val == 0, 0))
+	{
+	  __set_errno (EAGAIN);
+	  return -1;
+	}
+      oldval = val;
+    }
+  while ((val = lll_compare_and_swap ((int *) sem, oldval, oldval - 1))
+	 != oldval);
+  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
--- libc/nptl/sysdeps/unix/sysv/linux/ia64/sem_wait.c.jj	2003-03-07 13:06:30.000000000 -0500
+++ libc/nptl/sysdeps/unix/sysv/linux/ia64/sem_wait.c	2003-03-07 06:43:14.000000000 -0500
@@ -0,0 +1,63 @@
+/* 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 <errno.h>
+#include <sysdep.h>
+#include <lowlevelsem.h>
+#include <internaltypes.h>
+
+#include <shlib-compat.h>
+
+
+int
+__new_sem_wait (sem_t *sem)
+{
+  int oldval, val;
+
+  /* Atomically decrement semaphore counter if it is > 0.  */
+  val = *(int *) sem;
+  do
+    {
+      while (__builtin_expect (val == 0, 0))
+	{
+	  /* Do wait.  */
+	  int err = lll_futex_wait ((int *) sem, 0);
+
+	  /* Handle EINTR.  */
+	  if (err != 0 && err != -EWOULDBLOCK)
+	    {
+	      __set_errno (-err);
+	      return -1;
+	    }
+
+	  val = *(int *) sem;
+	}
+      oldval = val;
+    }
+  while ((val = lll_compare_and_swap ((int *) sem, oldval, oldval - 1))
+	 != oldval);
+
+  return 0;
+}
+
+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
--- libc/nptl/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h.jj	2003-03-07 13:06:30.000000000 -0500
+++ libc/nptl/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h	2003-03-06 16:26:07.000000000 -0500
@@ -0,0 +1,115 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub redhat com>, 2002.
+
+   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;									      \
+ENTRY (name)								      \
+     adds r14 = MULTIPLE_THREADS_OFFSET, r13;;				      \
+     ld4 r14 = [r14];							      \
+     mov r15 = SYS_ify(syscall_name);;					      \
+     cmp4.ne p6, p7 = 0, r14;						      \
+(p6) br.cond.spnt .Lpseudo_cancel;;					      \
+     break __BREAK_SYSCALL;;						      \
+     cmp.eq p6,p0=-1,r10;						      \
+(p6) br.cond.spnt.few __syscall_error;					      \
+     ret;;								      \
+.Lpseudo_cancel:							      \
+     .prologue;								      \
+     .regstk args, 5, args, 0;						      \
+     .save ar.pfs, loc0;						      \
+     alloc loc0 = ar.pfs, args, 5, args, 0;				      \
+     .save rp, loc1;							      \
+     mov loc1 = rp;;							      \
+     .body;								      \
+     CENABLE;;								      \
+     mov loc2 = r8;							      \
+     COPY_ARGS_##args							      \
+     mov r15 = SYS_ify(syscall_name);					      \
+     break __BREAK_SYSCALL;;						      \
+     mov loc3 = r8;							      \
+     mov loc4 = r10;							      \
+     mov out0 = loc2;							      \
+     CDISABLE;;								      \
+     cmp.eq p6,p0=-1,loc4;						      \
+(p6) br.cond.spnt.few __syscall_error_##args;				      \
+     mov r8 = loc3;							      \
+     mov rp = loc1;							      \
+     mov ar.pfs = loc0;							      \
+.Lpseudo_end:								      \
+     ret;								      \
+     .endp name;							      \
+.section .gnu.linkonce.t.__syscall_error_##args, "ax";			      \
+     .align 32;								      \
+     .proc __syscall_error_##args;					      \
+     .global __syscall_error_##args;					      \
+     .hidden __syscall_error_##args;					      \
+__syscall_error_##args:							      \
+     .prologue;								      \
+     .regstk args, 5, args, 0;						      \
+     .save ar.pfs, loc0;						      \
+     .save rp, loc1;							      \
+     .body;								      \
+     mov loc4 = r1;;							      \
+     br.call.sptk.many b0 = __errno_location;;				      \
+     st4 [r8] = loc3;							      \
+     mov r1 = loc4;							      \
+     mov rp = loc1;							      \
+     mov r8 = -1;							      \
+     mov ar.pfs = loc0
+
+# ifdef IS_IN_libpthread
+#  define CENABLE	br.call.sptk.many b0 = __pthread_enable_asynccancel
+#  define CDISABLE	br.call.sptk.many b0 = __pthread_disable_asynccancel
+# else
+#  define CENABLE	br.call.sptk.many b0 = __libc_enable_asynccancel
+#  define CDISABLE	br.call.sptk.many b0 = __libc_disable_asynccancel
+# endif
+
+#define COPY_ARGS_0	/* Nothing */
+#define COPY_ARGS_1	COPY_ARGS_0 mov out0 = in0;
+#define COPY_ARGS_2	COPY_ARGS_1 mov out1 = in1;
+#define COPY_ARGS_3	COPY_ARGS_2 mov out2 = in2;
+#define COPY_ARGS_4	COPY_ARGS_3 mov out3 = in3;
+#define COPY_ARGS_5	COPY_ARGS_4 mov out4 = in4;
+#define COPY_ARGS_6	COPY_ARGS_5 mov out5 = in5;
+#define COPY_ARGS_7	COPY_ARGS_6 mov out6 = in6;
+
+# ifndef __ASSEMBLER__
+#  define SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF, header.data.multiple_threads) == 0, 1)
+# else
+#  define SINGLE_THREAD_P \
+  adds r14 = MULTIPLE_THREADS_OFFSET, r13 ;; ld4 r14 = [r14] ;; cmp4.ne p6, p7 = 0, r14
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
--- libc/nptl/sysdeps/ia64/bits/atomic.h.jj	2003-03-07 13:05:38.000000000 -0500
+++ libc/nptl/sysdeps/ia64/bits/atomic.h	2003-03-07 10:24:51.000000000 -0500
@@ -0,0 +1,60 @@
+/* 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 <stdint.h>
+#include <ia64intrin.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) \
+  (!__sync_bool_compare_and_swap_si ((int *) (mem), (int) (long) (oldval), \
+				     (int) (long) (newval)))
+
+# define __arch_compare_and_exchange_64_acq(mem, newval, oldval) \
+  (!__sync_bool_compare_and_swap_di ((long *) (mem), (long) (oldval), \
+				     (long) (newval)))
--- libc/nptl/sysdeps/ia64/Makefile.jj	2003-03-07 13:05:50.000000000 -0500
+++ libc/nptl/sysdeps/ia64/Makefile	2003-03-07 17:34:09.000000000 -0500
@@ -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 ptw-sigblock ptw-sigprocmask
+endif
--- libc/nptl/sysdeps/ia64/pthread_spin_init.c.jj	2003-03-07 13:05:50.000000000 -0500
+++ libc/nptl/sysdeps/ia64/pthread_spin_init.c	2003-03-06 15:57:29.000000000 -0500
@@ -0,0 +1,20 @@
+/* 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.  */
+
+/* Not needed.  pthread_spin_init is an alias for pthread_spin_unlock.  */
--- libc/nptl/sysdeps/ia64/pthread_spin_lock.c.jj	2003-03-07 13:05:50.000000000 -0500
+++ libc/nptl/sysdeps/ia64/pthread_spin_lock.c	2003-03-06 15:57:48.000000000 -0500
@@ -0,0 +1,36 @@
+/* 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 "pthreadP.h"
+
+int
+pthread_spin_lock (lock)
+     pthread_spinlock_t *lock;
+{
+  int *p = (int *) lock;
+
+  while (__builtin_expect (__sync_val_compare_and_swap_si (p, 0, 1), 0))
+    {
+      /* Spin without using the atomic instruction.  */
+      do
+	__asm __volatile ("" : : : "memory");
+      while (*p);
+    }
+  return 0;
+}
--- libc/nptl/sysdeps/ia64/pthread_spin_trylock.c.jj	2003-03-07 13:05:50.000000000 -0500
+++ libc/nptl/sysdeps/ia64/pthread_spin_trylock.c	2003-03-06 15:59:44.000000000 -0500
@@ -0,0 +1,28 @@
+/* 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 <errno.h>
+#include "pthreadP.h"
+
+int
+pthread_spin_trylock (lock)
+     pthread_spinlock_t *lock;
+{
+  return __sync_val_compare_and_swap_si ((int *) lock, 0, 1) == 0 ? 0 : EBUSY;
+}
--- libc/nptl/sysdeps/ia64/pthread_spin_unlock.c.jj	2003-03-07 13:05:50.000000000 -0500
+++ libc/nptl/sysdeps/ia64/pthread_spin_unlock.c	2003-03-06 15:59:51.000000000 -0500
@@ -0,0 +1,31 @@
+/* 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.  */
+
+/* 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)
+{
+  *lock = 0;
+  return 0;
+}
+strong_alias (pthread_spin_unlock, pthread_spin_init)
--- libc/nptl/sysdeps/ia64/pthreaddef.h.jj	2003-03-07 13:05:50.000000000 -0500
+++ libc/nptl/sysdeps/ia64/pthreaddef.h	2003-03-07 19:05:26.000000000 -0500
@@ -0,0 +1,46 @@
+/* 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	(32 * 1024 * 1024)
+
+/* IA-64 uses a normal stack and a register stack.  */
+#define NEED_SEPARATE_REGISTER_STACK
+
+/* Required stack pointer alignment at beginning.  */
+#define STACK_ALIGN		16
+
+/* Minimal stack size after allocating thread descriptor and guard size.  */
+#define MINIMAL_REST_STACK	16384
+
+/* 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	__stack_pointer
+register char *__stack_pointer __asm__ ("sp");
+
+/* 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, 1, (val))
--- libc/nptl/sysdeps/ia64/tcb-offsets.sym.jj	2003-03-07 13:05:50.000000000 -0500
+++ libc/nptl/sysdeps/ia64/tcb-offsets.sym	2003-03-06 12:41:59.000000000 -0500
@@ -0,0 +1,4 @@
+#include <sysdep.h>
+#include <tls.h>
+
+MULTIPLE_THREADS_OFFSET offsetof (struct pthread, header.data.multiple_threads) - sizeof (struct pthread)
--- libc/nptl/sysdeps/ia64/td_ta_map_lwp2thr.c.jj	2003-03-07 13:05:50.000000000 -0500
+++ libc/nptl/sysdeps/ia64/td_ta_map_lwp2thr.c	2003-03-07 18:44:37.000000000 -0500
@@ -0,0 +1,46 @@
+/* Which thread is running on an LWP?  IA-64 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 "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[13], &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;
+}
--- libc/nptl/sysdeps/ia64/tls.h.jj	2003-03-07 13:05:50.000000000 -0500
+++ libc/nptl/sysdeps/ia64/tls.h	2003-03-07 10:57:13.000000000 -0500
@@ -0,0 +1,127 @@
+/* Definition for thread-local data handling.  nptl/IA-64 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
+{
+  dtv_t *dtv;
+  void *private;
+} 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.  */
+#define STACK_ALIGN	16
+
+#ifndef __ASSEMBLER__
+/* Get system call information.  */
+# include <sysdep.h>
+
+/* Get the thread descriptor definition.  */
+# include <nptl/descr.h>
+
+register struct pthread *__thread_self __asm__("r13");
+
+/* 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)
+
+/* This is the size we need before TCB.  */
+# define TLS_PRE_TCB_SIZE sizeof (struct pthread)
+
+/* Alignment requirements for the TCB.  */
+# define TLS_TCB_ALIGN __alignof__ (struct pthread)
+
+/* The DTV is allocated at the TP; the TCB is placed elsewhere.  */
+# 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(descr, dtvp) \
+  ((tcbhead_t *) (descr))->dtv = (dtvp) + 1
+
+/* Install new dtv for current thread.  */
+#  define INSTALL_NEW_DTV(DTV) \
+  (((tcbhead_t *)__thread_self)->dtv = (DTV))
+
+/* Return dtv of given thread descriptor.  */
+#  define GET_DTV(descr) \
+  (((tcbhead_t *) (descr))->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(thrdescr, secondcall) \
+  (__thread_self = (thrdescr), NULL)
+
+/* Return the address of the dtv for the current thread.  */
+#  define THREAD_DTV() \
+  (((tcbhead_t *)__thread_self)->dtv)
+
+/* Return the thread descriptor for the current thread.  */
+# define THREAD_SELF (__thread_self - 1)
+
+/* Access to data in the thread descriptor is easy.  */
+#define THREAD_GETMEM(descr, member) \
+  descr->member
+#define THREAD_GETMEM_NC(descr, member, idx) \
+  descr->member[idx]
+#define THREAD_SETMEM(descr, member, value) \
+  descr->member = (value)
+#define THREAD_SETMEM_NC(descr, member, idx, value) \
+  descr->member[idx] = (value)
+
+#endif /* __ASSEMBLER__ */
+
+#endif	/* tls.h */
--- libc/nptl/init.c.jj	2003-03-05 14:43:34.000000000 -0500
+++ libc/nptl/init.c	2003-03-07 08:43:03.000000000 -0500
@@ -37,6 +37,8 @@
    having the definition remove these lines.  */
 #if defined __s390__
 # define __NR_set_tid_address	252
+#elif defined __ia64__
+# define __NR_set_tid_address	1233
 #else
 # define __NR_set_tid_address	258
 #endif
--- libc/nptl/allocatestack.c.jj	2003-03-05 14:43:34.000000000 -0500
+++ libc/nptl/allocatestack.c	2003-03-07 18:35:07.000000000 -0500
@@ -29,6 +29,7 @@
 
 
 
+#ifndef NEED_SEPARATE_REGISTER_STACK
 
 /* Most architectures have exactly one stack pointer.  Some have more.  */
 #define STACK_VARIABLES void *stackaddr
@@ -39,6 +40,24 @@
 /* How to declare function which gets there parameters.  */
 #define STACK_VARIABLES_PARMS void *stackaddr
 
+/* How to declare allocate_stack.  */
+#define ALLOCATE_STACK_PARMS void **stack
+
+/* This is how the function is called.  We do it this way to allow
+   other variants of the function to have more parameters.  */
+#define ALLOCATE_STACK(attr, pd) allocate_stack (attr, pd, &stackaddr)
+
+#else
+
+#define STACK_VARIABLES void *stackaddr; size_t stacksize
+#define STACK_VARIABLES_ARGS stackaddr, stacksize
+#define STACK_VARIABLES_PARMS void *stackaddr, size_t stacksize
+#define ALLOCATE_STACK_PARMS void **stack, size_t *stacksize
+#define ALLOCATE_STACK(attr, pd) \
+  allocate_stack (attr, pd, &stackaddr, &stacksize)
+
+#endif
+
 
 /* Default alignment of stack.  */
 #ifndef STACK_ALIGN
@@ -58,6 +77,11 @@
 # define ARCH_MAP_FLAGS 0
 #endif
 
+#if TLS_TCB_AT_TP
+# define TLS_TPADJ(pd) (pd)
+#elif TLS_DTV_AT_TP
+# define TLS_TPADJ(pd) ((pd) + 1)
+#endif
 
 /* Cache handling for not-yet free stacks.  */
 
@@ -162,11 +186,13 @@ get_cached_stack (size_t *sizep, void **
   result->nextevent = NULL;
 
   /* Clear the DTV.  */
-  dtv_t *dtv = GET_DTV (result);
+  dtv_t *dtv = GET_DTV (TLS_TPADJ (result));
   memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t));
 
   /* Re-initialize the TLS.  */
-  return _dl_allocate_tls_init (result);
+  _dl_allocate_tls_init (TLS_TPADJ (result));
+
+  return result;
 }
 
 
@@ -222,11 +248,12 @@ queue_stack (struct pthread *stack)
 
 static int
 allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
-		void **stack)
+		ALLOCATE_STACK_PARMS)
 {
   struct pthread *pd;
   size_t size;
   size_t pagesize_m1 = __getpagesize () - 1;
+  void *stacktop;
 
   assert (attr != NULL);
   assert (powerof2 (pagesize_m1 + 1));
@@ -248,15 +275,27 @@ allocate_stack (const struct pthread_att
 	return EINVAL;
 
       /* Adjust stack size for alignment of the TLS block.  */
-      adj = ((uintptr_t) attr->stackaddr) & (__static_tls_align - 1);
+#if TLS_TCB_AT_TP
+      adj = ((uintptr_t) attr->stackaddr - TLS_TCB_SIZE)
+	    & (__static_tls_align - 1);
+      assert (size > adj + TLS_TCB_SIZE);
+#elif TLS_DTV_AT_TP
+      adj = ((uintptr_t) attr->stackaddr - __static_tls_size)
+	    & (__static_tls_align - 1);
       assert (size > adj);
+#endif
 
       /* The user provided some memory.  Let's hope it matches the
 	 size...  We do not allocate guard pages if the user provided
 	 the stack.  It is the user's responsibility to do this if it
 	 is wanted.  */
-      pd = (struct pthread *) (((uintptr_t) attr->stackaddr - adj)
-			       & ~(__alignof (struct pthread) - 1)) - 1;
+#if TLS_TCB_AT_TP
+      pd = (struct pthread *) ((uintptr_t) attr->stackaddr
+			       - TLS_TCB_SIZE - adj);
+#elif TLS_DTV_AT_TP
+      pd = (struct pthread *) ((uintptr_t) attr->stackaddr
+			       - __static_tls_size - adj) - 1;
+#endif
 
       /* The user provided stack memory needs to be cleared.  */
       memset (pd, '\0', sizeof (struct pthread));
@@ -287,7 +326,7 @@ allocate_stack (const struct pthread_att
 #endif
 
       /* Allocate the DTV for this thread.  */
-      if (_dl_allocate_tls (pd) == NULL)
+      if (_dl_allocate_tls (TLS_TPADJ (pd)) == NULL)
 	/* Something went wrong.  */
 	return errno;
 
@@ -369,7 +408,13 @@ allocate_stack (const struct pthread_att
 #endif
 
 	  /* Place the thread descriptor at the end of the stack.  */
+#if TLS_TCB_AT_TP
 	  pd = (struct pthread *) ((char *) mem + size - coloring) - 1;
+#elif TLS_DTV_AT_TP
+	  pd = (struct pthread *) (((uintptr_t) mem + size - coloring
+				    - __static_tls_size)
+				   & ~(__static_tls_align - 1)) - 1;
+#endif
 
 	  /* Remember the stack-related values.  */
 	  pd->stackblock = mem;
@@ -395,7 +440,7 @@ allocate_stack (const struct pthread_att
 #endif
 
 	  /* Allocate the DTV for this thread.  */
-	  if (_dl_allocate_tls (pd) == NULL)
+	  if (_dl_allocate_tls (TLS_TPADJ (pd)) == NULL)
 	    {
 	      /* Something went wrong.  */
 	      int err = errno;
@@ -427,7 +472,12 @@ allocate_stack (const struct pthread_att
       /* Create or resize the guard area if necessary.  */
       if (__builtin_expect (guardsize > pd->guardsize, 0))
 	{
-	  if (mprotect (mem, guardsize, PROT_NONE) != 0)
+#ifdef NEED_SEPARATE_REGISTER_STACK
+	  char *guard = mem + (((size - guardsize) / 2) & ~pagesize_m1);
+#else
+	  char *guard = mem;
+#endif
+	  if (mprotect (guard, guardsize, PROT_NONE) != 0)
 	    {
 	      int err;
 	    mprot_error:
@@ -456,9 +506,25 @@ allocate_stack (const struct pthread_att
 				 0))
 	{
 	  /* The old guard area is too large.  */
+
+#ifdef NEED_SEPARATE_REGISTER_STACK
+	  char *guard = mem + (((size - guardsize) / 2) & ~pagesize_m1);
+	  char *oldguard = mem + (((size - pd->guardsize) / 2) & ~pagesize_m1);
+
+	  if (oldguard < guard
+	      && mprotect (oldguard, guard - oldguard,
+			   PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
+	    goto mprot_error;
+
+	  if (mprotect (guard + guardsize,
+			oldguard + pd->guardsize - guard - guardsize,
+			PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
+	    goto mprot_error;
+#else
 	  if (mprotect ((char *) mem + guardsize, pd->guardsize - guardsize,
 			PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
 	    goto mprot_error;
+#endif
 
 	  pd->guardsize = guardsize;
 	}
@@ -469,18 +535,21 @@ allocate_stack (const struct pthread_att
 
 #if TLS_TCB_AT_TP
   /* The stack begins before the TCB and the static TLS block.  */
-  *stack = ((char *) (pd + 1) - __static_tls_size);
+  stacktop = ((char *) (pd + 1) - __static_tls_size);
+#elif TLS_DTV_AT_TP
+  stacktop = (char *) (pd - 1);
+#endif
+
+#ifdef NEED_SEPARATE_REGISTER_STACK
+  *stack = pd->stackblock;
+  *stacksize = stacktop - *stack;
 #else
-# error "Implement me"
+  *stack = stacktop;
 #endif
 
   return 0;
 }
 
-/* This is how the function is called.  We do it this way to allow
-   other variants of the function to have more parameters.  */
-#define ALLOCATE_STACK(attr, pd) allocate_stack (attr, pd, &stackaddr)
-
 
 void
 internal_function
@@ -500,7 +569,7 @@ __deallocate_stack (struct pthread *pd)
     (void) queue_stack (pd);
   else
     /* Free the memory associated with the ELF TLS.  */
-    _dl_deallocate_tls (pd, false);
+    _dl_deallocate_tls (TLS_TPADJ (pd), false);
 
   lll_unlock (stack_cache_lock);
 }


	Jakub





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