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

glibc pthreads support for HPPA



libc-alpha,

This is the first of the of ~nine hppa patches; it is by far the
largest of all the patches (think orders of magnitude).

HPPA has a single atomic operation, namely 'ldcw', which requires
that we initialize locks to one instead of zero. Please keep
this in mind when reviewing the code.

Comments and feedback would be wonderful :)

This is my first time doing a forward-feed of something like
this, so please be patient if the first try takes a little 
iteration.

---
2002-18-09	Carlos O'Donell	<carlos@baldric.uwo.ca>

	2002-10-09 Carlos O'Donell <carlos@baldric.uwo.ca>

	* linuxthreads/descr.h:
	In "struct pthread_atomic" change "int p_spinlock" 
	to "__atomic_lock_t p_spinlock"

	2001-11-14 Matthew Wilcox <willy@debian.org>

	* linuxthreads/oldsemaphore.c:
	(__old_sem_init): Change "__LT_SPINLOCK_INIT" to 
	"__ATOMIC_LOCK_INIT".

	* linuxthreads/pt-machine.c: Define extern for "try_lock"
	function call.

	* linuxthreads/spinlock.c:
	Change "int * spinlock" to "__atomic_lock_t * spinlock",
	"__LT_SPINLOCK_INIT" to "__ATOMIC_LOCK_INIT", and
	"0" to "__ATOMIC_LOCK_INIT", where required.
	In "struct wait_node" change "int abandoned" to
	"__atomic_lock_t abandoned"
	
	(__pthread_release): Function call argument changed from
	"int * spinlock" to "__atomic_lock_t * spinlock", and 
	"__LT_SPINLOCK_INIT" changed to "__ATOMIC_LOCK_INIT".
	
	(__pthread_alt_timedlock): "0" to "__ATOMIC_LOCK_INIT" and
	change calls from "testandset" to "try_lock";
	
	(__pthread_alt_unlock): "0" to "__ATOMIC_LOCK_INIT", and
	"p_node->abandoned" to "lock_held(&p_node->abandoned)", and
	changed calls from "testandset" to "try_lock" where required.

	(__pthread_compare_and_swap): Function call argument changed from
        "int * spinlock" to "__atomic_lock_t * spinlock".

	(__pthread_acquire): Function call argument changed from
        "int * spinlock" to "__atomic_lock_t * spinlock", and 		
	changed calls from "testandset" to "try_lock" where required.

	* linuxthreads/spinlock.h:
	Remove testandset macro.
	(__pthread_compare_and_swap): Extern changed to match function.
	(compare_and_swap): Likewise.
	(compare_and_swap_with_release_semantics): Function arg. type change.
	(compare_and_swap): Function arg. type change.
	(__pthread_compare_and_swap): Extern changed to match function.
	(__pthread_init_lock): "__LT_SPINLOCK_INIT" changed to
	"__ATOMIC_LOCK_INIT".
	(__pthread_alt_trylock): "__LT_SPINLOCK_INIT" to 
	"__ATOMIC_LOCK_INIT" and change calls from "testandset" to 
	"try_lock".
			
	* linuxthreads/sysdeps/alpha/pt-machine.h:
	(testandset): Deleted (renamed to try_lock).
	(try_lock): New. 
	(lock_held): New.
	* linuxthreads/sysdeps/arm/pt-machine.h: Likewise.
	* linuxthreads/sysdeps/cris/pt-machine.h: Likewise.
	* linuxthreads/sysdeps/i386/i686/pt-machine.h: Likewise.
	* linuxthreads/sysdeps/i386/pt-machine.h: Likewise.
	* linuxthreads/sysdeps/ia64/pt-machine.h: Likewise.	
	* linuxthreads/sysdeps/m68k/pt-machine.h: Likewise.
	* linuxthreads/sysdeps/mips/pt-machine.h: Likewise.	
	* linuxthreads/sysdeps/powerpc/pt-machine.h: Likewise.
	* linuxthreads/sysdeps/s390/s390-32/pt-machine.h: Likewise.
	* linuxthreads/sysdeps/s390/s390-64/pt-machine.h: Likewise.
	* linuxthreads/sysdeps/sh/pt-machine.h: Likewise.
	* linuxthreads/sysdeps/sparc/sparc32/pt-machine.h: Likewise.
	* linuxthreads/sysdeps/sparc/sparc64/pt-machine.h: Likewise.

	* linuxthreads/sysdeps/pthread/bits/pthreadtypes.h:
	typedef __atomic_lock_t to int for all other arches
	leaving them the same as before.
	(_pthread_fastlock): Change "int" to "__atomic_lock_t".
	* linuxthreads/sysdeps/pthread/bits/libc-lock.h:
	Include the use of PTHREAD_MUTEX_INITIALIZER for
	the case of __LOCK_INITIALISER_NOT_ZERO.
	* linuxthreads/sysdeps/pthread/bits/initspin.h: 
	Define __ATOMIC_LOCK_INIT as 0 for all arches.
	Include changes to associated macros.
	* linuxthreads/sysdeps/hppa/pspinlock.c :
	(__ldcw): New.
	(__pthread_spin_lock): Cleanup.
	(__pthread_spin_trylock): Cleanup.
	* linuxthreads/sysdeps/hppa/pt-machine.h:
	(__get_cr27): New.
	(__set_cr27): New.
	(testandset): Deleted (renamed to try_lock).
        (try_lock): New.
	(lock_held): New.

	* linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/initspin.h:
	Remove "__LT_SPINLOCK_INIT" and define "__ATOMIC_LOCK_INIT"
	to "((__atomic_lock_t) { 1 })" while changing the associated
	macros that relied on this.

	* linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/pthreadtypes.h:
	New file.
	* sysdeps/hppa/dl-fptr.c:
	Change the use of "1" to "__ATOMIC_LOCK_INIT".
	(__hppa_make_fptr): Call 'try_lock' instead of 'testandset',
	and change the use of "1" to "__ATOMIC_LOCK_INIT".
	(_dl_unmap): Likewise.
	(_dl_lookup_address): Likewise.
        * sysdeps/ia64/dl-fptr.c:
	In "static struct local" change "int lock" to
	"__atomic_lock_t lock"
	(lock): Change calls from "testandset" to "try_lock",
	and change "0" to "__ATOMIC_LOCK_INIT" where needed.
        * sysdeps/unix/sysv/linux/hppa/bits/ipc.h:
        New file.
        * sysdeps/unix/sysv/linux/hppa/bits/msq.h:
        New file.
        * sysdeps/unix/sysv/linux/hppa/bits/sem.h:
        New file.
        * sysdeps/unix/sysv/linux/hppa/bits/shm.h:
        New file.

diff -urN libc/linuxthreads/descr.h libc/linuxthreads/descr.h
--- libc/linuxthreads/descr.h     2002-08-01 23:31:54.000000000 -0400
+++ libc/linuxthreads/descr.h     2002-09-02 14:49:22.000000000 -0400
@@ -61,7 +61,7 @@
 /* Atomic counter made possible by compare_and_swap */
 struct pthread_atomic {
   long p_count;
-  int p_spinlock;
+  __atomic_lock_t p_spinlock;
 };
 
 
diff -urN libc/linuxthreads/oldsemaphore.c libc/linuxthreads/oldsemaphore.c
--- libc/linuxthreads/oldsemaphore.c	Wed Nov 14 09:47:09 2001
+++ libc/linuxthreads/oldsemaphore.c	Wed Nov 14 09:43:58 2001
@@ -73,7 +73,7 @@
 	errno = ENOSYS;
 	return -1;
     }
-  sem->sem_spinlock = __LT_SPINLOCK_INIT;
+  sem->sem_spinlock = __ATOMIC_LOCK_INIT;
   sem->sem_status = ((long)value << 1) + 1;
   return 0;
 }
diff -urN libc/linuxthreads/pt-machine.c libc/linuxthreads/pt-machine.c
--- libc/linuxthreads/pt-machine.c	Wed Nov 14 09:47:09 2001
+++ libc/linuxthreads/pt-machine.c	Wed Nov 14 09:43:58 2001
@@ -19,7 +19,9 @@
 
 #define PT_EI
 
-extern long int testandset (int *spinlock);
+#include <pthread.h>
+
+extern int try_lock(__atomic_lock_t *spinlock);
 extern int __compare_and_swap (long int *p, long int oldval, long int newval);
 
 #include <pt-machine.h>
diff -urN libc/linuxthreads/spinlock.c libc/linuxthreads/spinlock.c
--- libc/linuxthreads/spinlock.c	Wed Nov 14 09:47:09 2001
+++ libc/linuxthreads/spinlock.c	Wed Nov 14 09:43:58 2001
@@ -24,12 +24,12 @@
 #include "spinlock.h"
 #include "restart.h"
 
-static void __pthread_acquire(int * spinlock);
+static void __pthread_acquire(__atomic_lock_t * spinlock);
 
-static inline void __pthread_release(int * spinlock)
+static inline void __pthread_release(__atomic_lock_t * spinlock)
 {
   WRITE_MEMORY_BARRIER();
-  *spinlock = __LT_SPINLOCK_INIT;
+  *spinlock = __ATOMIC_LOCK_INIT;
   __asm __volatile ("" : "=m" (*spinlock) : "0" (*spinlock));
 }
 
@@ -269,11 +269,11 @@
 struct wait_node {
   struct wait_node *next;	/* Next node in null terminated linked list */
   pthread_descr thr;		/* The thread waiting with this node */
-  int abandoned;		/* Atomic flag */
+  __atomic_lock_t abandoned;		/* Atomic flag */
 };
 
 static long wait_node_free_list;
-static int wait_node_free_list_spinlock;
+static __atomic_lock_t wait_node_free_list_spinlock = __ATOMIC_LOCK_INIT;
 
 /* Allocate a new node from the head of the free list using an atomic
    operation, or else using malloc if that list is empty.  A fundamental
@@ -427,7 +425,7 @@
       if (self == NULL)
 	self = thread_self();
 
-      wait_node.abandoned = 0;
+      wait_node.abandoned = __ATOMIC_LOCK_INIT;
       wait_node.next = (struct wait_node *) lock->__status;
       wait_node.thr = self;
       lock->__status = (long) &wait_node;
@@ -453,7 +451,7 @@
       wait_node.thr = self;
       newstatus = (long) &wait_node;
     }
-    wait_node.abandoned = 0;
+    wait_node.abandoned = __ATOMIC_LOCK_INIT;
     wait_node.next = (struct wait_node *) oldstatus;
     /* Make sure the store in wait_node.next completes before performing
        the compare-and-swap */
@@ -502,7 +500,7 @@
       if (self == NULL)
 	self = thread_self();
 
-      p_wait_node->abandoned = 0;
+      p_wait_node->abandoned = __ATOMIC_LOCK_INIT;
       p_wait_node->next = (struct wait_node *) lock->__status;
       p_wait_node->thr = self;
       lock->__status = (long) p_wait_node;
@@ -525,7 +523,7 @@
       p_wait_node->thr = self;
       newstatus = (long) p_wait_node;
     }
-    p_wait_node->abandoned = 0;
+    p_wait_node->abandoned = __ATOMIC_LOCK_INIT;
     p_wait_node->next = (struct wait_node *) oldstatus;
     /* Make sure the store in wait_node.next completes before performing
        the compare-and-swap */
@@ -546,7 +544,7 @@
 
   if (oldstatus != 0) {
     if (timedsuspend(self, abstime) == 0) {
-      if (!testandset(&p_wait_node->abandoned))
+      if (!try_lock(&p_wait_node->abandoned))
 	return 0; /* Timeout! */
 
       /* Eat oustanding resume from owner, otherwise wait_node_free() below
@@ -625,7 +623,7 @@
     while (p_node != (struct wait_node *) 1) {
       int prio;
 
-      if (p_node->abandoned) {
+      if (lock_held(&p_node->abandoned)) {
 	/* Remove abandoned node. */
 #if defined TEST_FOR_COMPARE_AND_SWAP
 	if (!__pthread_has_cas)
@@ -656,7 +654,7 @@
 	p_max_prio = p_node;
       }
 
-      /* This canno6 jump backward in the list, so no further read
+      /* This cannot jump backward in the list, so no further read
          barrier is needed. */
       pp_node = &p_node->next;
       p_node = *pp_node;
@@ -675,7 +673,7 @@
        thread timed out and abandoned the node in which case we repeat the
        whole unlock operation. */
 
-    if (!testandset(&p_max_prio->abandoned)) {
+    if (!try_lock(&p_max_prio->abandoned)) {
 #if defined TEST_FOR_COMPARE_AND_SWAP
       if (!__pthread_has_cas)
 #endif
@@ -713,7 +711,7 @@
 #if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
 
 int __pthread_compare_and_swap(long * ptr, long oldval, long newval,
-                               int * spinlock)
+                               __atomic_lock_t * spinlock)
 {
   int res;
 
@@ -751,14 +749,14 @@
    - When nanosleep() returns, we try again, doing MAX_SPIN_COUNT
      sched_yield(), then sleeping again if needed. */
 
-static void __pthread_acquire(int * spinlock)
+static void __pthread_acquire(__atomic_lock_t * spinlock)
 {
   int cnt = 0;
   struct timespec tm;
 
   READ_MEMORY_BARRIER();
 
-  while (testandset(spinlock)) {
+  while (try_lock(spinlock)) {
     if (cnt < MAX_SPIN_COUNT) {
       sched_yield();
       cnt++;
diff -urN libc/linuxthreads/spinlock.h libc/linuxthreads/spinlock.h
--- libc/linuxthreads/spinlock.h	Wed Nov 14 09:47:09 2001
+++ libc/linuxthreads/spinlock.h	Wed Nov 14 09:43:58 2001
@@ -14,7 +14,6 @@
 
 #include <bits/initspin.h>
 
-
 /* There are 2 compare and swap synchronization primitives with
    different semantics:
 
@@ -37,10 +36,10 @@
 
 extern int __pthread_has_cas;
 extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval,
-                                      int * spinlock);
+                                      __atomic_lock_t * spinlock);
 
 static inline int compare_and_swap(long * ptr, long oldval, long newval,
-                                   int * spinlock)
+                                   __atomic_lock_t * spinlock)
 {
   if (__builtin_expect (__pthread_has_cas, 1))
     return __compare_and_swap(ptr, oldval, newval);
@@ -50,15 +49,11 @@
 
 #elif defined(HAS_COMPARE_AND_SWAP)
 
-#ifdef IMPLEMENT_TAS_WITH_CAS
-#define testandset(p) !__compare_and_swap((long int *) p, 0, 1)
-#endif
-
 #ifdef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
 
 static inline int
 compare_and_swap_with_release_semantics (long * ptr, long oldval,
-					 long newval, int * spinlock)
+					 long newval, __atomic_lock_t * spinlock)
 {
   return __compare_and_swap_with_release_semantics (ptr, oldval,
 						    newval);
@@ -67,7 +62,7 @@
 #endif
 
 static inline int compare_and_swap(long * ptr, long oldval, long newval,
-                                   int * spinlock)
+                                   __atomic_lock_t * spinlock)
 {
   return __compare_and_swap(ptr, oldval, newval);
 }
@@ -75,10 +70,10 @@
 #else
 
 extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval,
-                                      int * spinlock);
+                                      __atomic_lock_t * spinlock);
 
 static inline int compare_and_swap(long * ptr, long oldval, long newval,
-                                   int * spinlock)
+                                   __atomic_lock_t * spinlock)
 {
   return __pthread_compare_and_swap(ptr, oldval, newval, spinlock);
 }
@@ -99,7 +94,7 @@
 static inline void __pthread_init_lock(struct _pthread_fastlock * lock)
 {
   lock->__status = 0;
-  lock->__spinlock = __LT_SPINLOCK_INIT;
+  lock->__spinlock = __ATOMIC_LOCK_INIT;
 }
 
 static inline int __pthread_trylock (struct _pthread_fastlock * lock)
@@ -109,7 +104,7 @@
 #endif
 #if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
   {
-    return (testandset(&lock->__spinlock) ? EBUSY : 0);
+    return (try_lock(&lock->__spinlock) ? EBUSY : 0);
   }
 #endif
 
@@ -136,7 +131,7 @@
 static inline void __pthread_alt_init_lock(struct _pthread_fastlock * lock)
 {
   lock->__status = 0;
-  lock->__spinlock = __LT_SPINLOCK_INIT;
+  lock->__spinlock = __ATOMIC_LOCK_INIT;
 }
 
 static inline int __pthread_alt_trylock (struct _pthread_fastlock * lock)
@@ -148,7 +143,7 @@
   {
     int res = EBUSY;
 
-    if (testandset(&lock->__spinlock) == 0)
+    if (try_lock(&lock->__spinlock) == 0)
       {
 	if (lock->__status == 0)
 	  {
@@ -156,7 +151,7 @@
 	    WRITE_MEMORY_BARRIER();
 	    res = 0;
 	  }
-	lock->__spinlock = __LT_SPINLOCK_INIT;
+	lock->__spinlock = __ATOMIC_LOCK_INIT;
       }
     return res;
   }
diff -urN libc/linuxthreads/sysdeps/alpha/pt-machine.h libc/linuxthreads/sysdeps/alpha/pt-machine.h
--- libc/linuxthreads/sysdeps/alpha/pt-machine.h	Wed Nov 14 09:47:09 2001
+++ libc/linuxthreads/sysdeps/alpha/pt-machine.h	Wed Nov 14 09:43:58 2001
@@ -39,8 +39,8 @@
 
 
 /* Spinlock implementation; required.  */
-PT_EI long int
-testandset (int *spinlock)
+PT_EI int
+try_lock (int *spinlock)
 {
   long int ret, temp;
 
@@ -58,9 +58,10 @@
 	: "m"(*spinlock)
         : "memory");
 
-  return ret;
+  return (int) ret;
 }
 
+#define lock_held(p) *(p)
 
 /* Begin allocating thread stacks at this address.  Default is to allocate
    them just below the initial program stack.  */
diff -urN libc/linuxthreads/sysdeps/arm/pt-machine.h libc/linuxthreads/sysdeps/arm/pt-machine.h
--- libc/linuxthreads/sysdeps/arm/pt-machine.h	Wed Nov 14 09:47:09 2001
+++ libc/linuxthreads/sysdeps/arm/pt-machine.h	Wed Nov 14 09:43:58 2001
@@ -29,8 +29,8 @@
    time; let's hope nobody tries to use one.  */
 
 /* Spinlock implementation; required.  */
-PT_EI long int
-testandset (int *spinlock)
+PT_EI int
+try_lock(__atomic_lock_t *spinlock)
 {
   register unsigned int ret;
 
@@ -41,6 +41,7 @@
   return ret;
 }
 
+#define lock_held(p) *(p)
 
 /* Get some notion of the current stack.  Need not be exactly the top
    of the stack, just something somewhere in the current frame.  */
diff -urN libc/linuxthreads/sysdeps/cris/pt-machine.h libc/linuxthreads/sysdeps/cris/pt-machine.h
--- libc/linuxthreads/sysdeps/cris/pt-machine.h	Wed Nov 14 09:47:09 2001
+++ libc/linuxthreads/sysdeps/cris/pt-machine.h	Wed Nov 14 09:43:58 2001
@@ -22,10 +22,10 @@
 # define PT_EI extern inline
 #endif
 
-PT_EI long int
-testandset (int *spinlock)
+PT_EI int
+try_lock(__atomic_lock_t *spinlock)
 {
-  register unsigned long int ret;
+  register unsigned int ret;
 
   /* Note the use of a dummy output of *spinlock to expose the write.  The
      memory barrier is to stop *other* writes being moved past this code.  */
@@ -42,6 +42,7 @@
   return ret;
 }
 
+#define lock_held(p) *(p)
 
 /* Get some notion of the current stack.  Need not be exactly the top
    of the stack, just something somewhere in the current frame.
diff -urN libc/linuxthreads/sysdeps/hppa/pspinlock.c libc/linuxthreads/sysdeps/hppa/pspinlock.c
--- libc/linuxthreads/sysdeps/hppa/pspinlock.c	Wed Nov 14 09:47:09 2001
+++ libc/linuxthreads/sysdeps/hppa/pspinlock.c	Wed Nov 14 09:43:58 2001
@@ -21,18 +21,20 @@
 #include <pthread.h>
 #include "internals.h"
 
+/* LDCW, the only atomic read-write operation PA-RISC has. *sigh*.  */
+#define __ldcw(a) ({ \
+	unsigned __ret; \
+	__asm__ __volatile__("ldcw 0(%1),%0" : "=r" (__ret) : "r" (a)); \
+	__ret; \
+})
+
 int
 __pthread_spin_lock (pthread_spinlock_t *lock)
 {
-  unsigned int val;
-
-  do
-    asm volatile ("ldcw %1,%0"
-		  : "=r" (val), "=m" (*lock)
-		  : "m" (*lock));
-  while (!val);
+	while (__ldcw (*lock) == 0)
+		while (*lock == 0) ;
 
-  return 0;
+	return 0;
 }
 weak_alias (__pthread_spin_lock, pthread_spin_lock)
 
@@ -40,11 +42,7 @@
 int
 __pthread_spin_trylock (pthread_spinlock_t *lock)
 {
-  unsigned int val;
-
-  asm volatile ("ldcw %1,%0"
-		: "=r" (val), "=m" (*lock)
-		: "m" (*lock));
+  unsigned int val = __ldcw(*lock);
 
   return val ? 0 : EBUSY;
 }
diff -urN libc/linuxthreads/sysdeps/hppa/pt-machine.h libc/linuxthreads/sysdeps/hppa/pt-machine.h
--- libc/linuxthreads/sysdeps/hppa/pt-machine.h	Wed Nov 14 09:47:09 2001
+++ libc/linuxthreads/sysdeps/hppa/pt-machine.h	Wed Nov 14 09:43:58 2001
@@ -19,6 +19,7 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
+#include <sys/types.h>
 #include <bits/initspin.h>
 
 #ifndef PT_EI
@@ -30,16 +31,39 @@
 #define CURRENT_STACK_FRAME  stack_pointer
 register char * stack_pointer __asm__ ("%r30");
 
+/* Get/Set thread-specific pointer.  We have to call into the kernel to
+ * modify it, but we can read it in user mode.  */
+
+#define THREAD_SELF __get_cr27()
+
+static inline struct _pthread_descr_struct * __get_cr27(void)
+{
+	long cr27;
+	asm("mfctl %%cr27, %0" : "=r" (cr27) : );
+	return (struct _pthread_descr_struct *) cr27;
+}
+
+#define INIT_THREAD_SELF(descr, nr) __set_cr27(descr)
+
+static inline void __set_cr27(struct _pthread_descr_struct * cr27)
+{
+	asm(
+		"ble	0xe0(%%sr2, %%r0)\n\t"
+		"copy	%0, %%r26"
+	 : : "r" (cr27) : "r26" );
+}
+
+/* We want the OS to assign stack addresses.  */
+#define FLOATING_STACKS	1
+#define ARCH_STACK_MAX_SIZE	8*1024*1024
 
 /* The hppa only has one atomic read and modify memory operation,
    load and clear, so hppa spinlocks must use zero to signify that
    someone is holding the lock.  */
 
-#define xstr(s) str(s)
-#define str(s) #s
 /* Spinlock implementation; required.  */
-PT_EI long int
-testandset (int *spinlock)
+PT_EI int
+try_lock(__atomic_lock_t *spinlock)
 {
   int ret;
 
@@ -80,7 +80,11 @@
 
   return ret == 0;
 }
-#undef str
-#undef xstr
 
+PT_EI int
+lock_held(__atomic_lock_t *spinlock)
+{
+	return spinlock->lock == 0;
+}
+		
 #endif /* pt-machine.h */
diff -urN libc/linuxthreads/sysdeps/i386/i686/pt-machine.h libc/linuxthreads/sysdeps/i386/i686/pt-machine.h
--- libc/linuxthreads/sysdeps/i386/i686/pt-machine.h	Wed Nov 14 09:47:09 2001
+++ libc/linuxthreads/sysdeps/i386/i686/pt-machine.h	Wed Nov 14 09:43:58 2001
@@ -30,10 +30,10 @@
 
 
 /* Spinlock implementation; required.  */
-PT_EI long int
-testandset (int *spinlock)
+PT_EI int
+try_lock (int *spinlock)
 {
-  long int ret;
+  int ret;
 
   __asm__ __volatile__ (
 	"xchgl %0, %1"
@@ -44,6 +44,7 @@
   return ret;
 }
 
+#define lock_held(p) *(p)
 
 /* Compare-and-swap for semaphores.  It's always available on i686.  */
 #define HAS_COMPARE_AND_SWAP
diff -urN libc/linuxthreads/sysdeps/i386/pt-machine.h libc/linuxthreads/sysdeps/i386/pt-machine.h
--- libc/linuxthreads/sysdeps/i386/pt-machine.h	Wed Nov 14 09:47:09 2001
+++ libc/linuxthreads/sysdeps/i386/pt-machine.h	Wed Nov 14 09:43:58 2001
@@ -29,10 +29,10 @@
 
 
 /* Spinlock implementation; required.  */
-PT_EI long int
-testandset (int *spinlock)
+PT_EI int
+try_lock(__atomic_lock_t *spinlock)
 {
-  long int ret;
+  int ret;
 
   __asm__ __volatile__(
        "xchgl %0, %1"
@@ -43,6 +43,7 @@
   return ret;
 }
 
+#define lock_held(p) *(p)
 
 /* Compare-and-swap for semaphores.
    Available on the 486 and above, but not on the 386.
diff -urN libc/linuxthreads/sysdeps/ia64/pt-machine.h libc/linuxthreads/sysdeps/ia64/pt-machine.h
--- libc/linuxthreads/sysdeps/ia64/pt-machine.h	Wed Nov 14 09:47:09 2001
+++ libc/linuxthreads/sysdeps/ia64/pt-machine.h	Wed Nov 14 09:43:58 2001
@@ -97,8 +97,8 @@
 #endif /* ELF_MACHINE_NAME */
 
 /* Spinlock implementation; required.  */
-PT_EI long int
-testandset (int *spinlock)
+PT_EI int
+try_lock(__atomic_lock_t *spinlock)
 {
   long int ret;
 
@@ -120,7 +120,9 @@
        : "r"(1), "1"(__atomic_fool_gcc (spinlock))
        : "memory");
 
-  return ret;
+  return (int) ret;
 }
 
+#define lock_held(p) *(p)
+
 #endif /* pt-machine.h */
diff -urN libc/linuxthreads/sysdeps/m68k/pt-machine.h libc/linuxthreads/sysdeps/m68k/pt-machine.h
--- libc/linuxthreads/sysdeps/m68k/pt-machine.h	Wed Nov 14 09:47:09 2001
+++ libc/linuxthreads/sysdeps/m68k/pt-machine.h	Wed Nov 14 09:43:58 2001
@@ -25,8 +25,8 @@
 
 
 /* Spinlock implementation; required.  */
-PT_EI long int
-testandset (int *spinlock)
+PT_EI int
+try_lock(__atomic_lock_t *spinlock)
 {
   char ret;
 
@@ -38,6 +38,7 @@
   return ret;
 }
 
+#define lock_held(p) *(p)
 
 /* Get some notion of the current stack.  Need not be exactly the top
    of the stack, just something somewhere in the current frame.  */
diff -urN libc/linuxthreads/sysdeps/mips/pt-machine.h libc/linuxthreads/sysdeps/mips/pt-machine.h
--- libc/linuxthreads/sysdeps/mips/pt-machine.h	Sat Mar  2 19:37:24 2002
+++ libc/linuxthreads/sysdeps/mips/pt-machine.h	Sat Mar  2 19:38:20 2002
@@ -33,12 +33,13 @@
 
 /* Spinlock implementation; required.  */
 
-PT_EI long int
-testandset (int *spinlock)
+PT_EI int
+try_lock (__atomic_lock_t *spinlock)
 {
   return _test_and_set (spinlock, 1);
 }
 
+#define lock_held(p) *(p)
 
 /* Get some notion of the current stack.  Need not be exactly the top
    of the stack, just something somewhere in the current frame.  */
diff -urN libc/linuxthreads/sysdeps/powerpc/pt-machine.h libc/linuxthreads/sysdeps/powerpc/pt-machine.h
--- libc/linuxthreads/sysdeps/powerpc/pt-machine.h	Wed Nov 14 09:47:09 2001
+++ libc/linuxthreads/sysdeps/powerpc/pt-machine.h	Wed Nov 14 09:43:58 2001
@@ -39,7 +39,13 @@
 /* note that test-and-set(x) is the same as !compare-and-swap(x, 0, 1) */
 
 #define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
-#define IMPLEMENT_TAS_WITH_CAS
+
+static inline int try_lock(__atomic_lock_t *p)
+{
+  return !__compare_and_swap((long int *) p, 0, 1);
+}
+
+#define lock_held(p) *(p)
 
 PT_EI int
 __compare_and_swap (long int *p, long int oldval, long int newval)
diff -urN libc/linuxthreads/sysdeps/pthread/bits/initspin.h libc/linuxthreads/sysdeps/pthread/bits/initspin.h
--- libc/linuxthreads/sysdeps/pthread/bits/initspin.h	Wed Nov 14 09:47:09 2001
+++ libc/linuxthreads/sysdeps/pthread/bits/initspin.h	Wed Nov 14 09:43:58 2001
@@ -20,9 +20,8 @@
 /* Initial value of a spinlock.  Most platforms should use zero,
    unless they only implement a "test and clear" operation instead of
    the usual "test and set". */
-#define __LT_SPINLOCK_INIT 0
+#define __ATOMIC_LOCK_INIT  0
 
 /* Macros for lock initializers, using the above definition. */
-#define __LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT }
-#define __ALT_LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT }
-#define __ATOMIC_INITIALIZER { 0, __LT_SPINLOCK_INIT }
+#define __LOCK_INITIALIZER { 0, 0 }
+#define __ATOMIC_INITIALIZER { 0, 0 }
diff -urN libc/linuxthreads/sysdeps/pthread/bits/libc-lock.h libc/linuxthreads/sysdeps/pthread/bits/libc-lock.h
--- libc/linuxthreads/sysdeps/pthread/bits/libc-lock.h	Wed Nov 14 09:47:09 2001
+++ libc/linuxthreads/sysdeps/pthread/bits/libc-lock.h	Wed Nov 14 09:43:58 2001
@@ -63,12 +63,12 @@
    initialized locks must be set to one due to the lack of normal
    atomic operations.) */
 
-#if __LT_SPINLOCK_INIT == 0
+#ifdef __LOCK_INITIALISER_NOT_ZERO
 #  define __libc_lock_define_initialized(CLASS,NAME) \
-  CLASS __libc_lock_t NAME;
+  CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER;
 #else
 #  define __libc_lock_define_initialized(CLASS,NAME) \
-  CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER;
+  CLASS __libc_lock_t NAME;
 #endif
 
 #define __libc_rwlock_define_initialized(CLASS,NAME) \
diff -urN libc/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h libc/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h
--- libc/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h	Wed Nov 14 09:47:09 2001
+++ libc/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h	Wed Nov 14 09:43:58 2001
@@ -22,11 +22,13 @@
 #define __need_schedparam
 #include <bits/sched.h>
 
+typedef int __atomic_lock_t;
+
 /* Fast locks (not abstract because mutexes and conditions aren't abstract). */
 struct _pthread_fastlock
 {
   long int __status;   /* "Free" or "taken" or head of waiting list */
-  int __spinlock;      /* Used by compare_and_swap emulation. Also,
+  __atomic_lock_t __spinlock;  /* Used by compare_and_swap emulation. Also,
 			  adaptive SMP lock stores spin count here. */
 };
 
diff -urN libc/linuxthreads/sysdeps/s390/s390-32/pt-machine.h libc/linuxthreads/sysdeps/s390/s390-32/pt-machine.h
--- libc/linuxthreads/sysdeps/s390/s390-32/pt-machine.h	Wed Nov 14 09:47:09 2001
+++ libc/linuxthreads/sysdeps/s390/s390-32/pt-machine.h	Wed Nov 14 09:43:58 2001
@@ -24,8 +24,8 @@
 #endif
 
 /* Spinlock implementation; required.  */
-PT_EI long int
-testandset (int *spinlock)
+PT_EI int
+try_lock (int *spinlock)
 {
   int ret;
 
@@ -41,6 +41,7 @@
   return ret;
 }
 
+#define lock_held(p) *(p)
 
 /* Get some notion of the current stack.  Need not be exactly the top
    of the stack, just something somewhere in the current frame.  */
diff -urN libc/linuxthreads/sysdeps/s390/s390-64/pt-machine.h libc/linuxthreads/sysdeps/s390/s390-64/pt-machine.h
--- libc/linuxthreads/sysdeps/s390/s390-64/pt-machine.h	Wed Nov 14 09:47:09 2001
+++ libc/linuxthreads/sysdeps/s390/s390-64/pt-machine.h	Wed Nov 14 09:43:58 2001
@@ -24,7 +24,7 @@
 #endif
 
 /* Spinlock implementation; required.  */
-PT_EI long int
+PT_EI int
 testandset (int *spinlock)
 {
   int ret;
@@ -41,6 +41,7 @@
   return ret;
 }
 
+#define lock_held(p) *(p)
 
 /* Get some notion of the current stack.  Need not be exactly the top
    of the stack, just something somewhere in the current frame.  */
diff -urN libc/linuxthreads/sysdeps/sh/pt-machine.h libc/linuxthreads/sysdeps/sh/pt-machine.h
--- libc/linuxthreads/sysdeps/sh/pt-machine.h	Wed Nov 14 09:47:09 2001
+++ libc/linuxthreads/sysdeps/sh/pt-machine.h	Wed Nov 14 09:43:58 2001
@@ -24,8 +24,8 @@
 #endif
 
 /* Spinlock implementation; required.  */
-PT_EI long int
-testandset (int *spinlock)
+PT_EI int
+try_lock(__atomic_lock_t *spinlock)
 {
   int ret;

@@ -45,6 +45,8 @@
   return (ret == 0);
 }
 
+#define lock_held(p) *(p)
+
 /* We want the OS to assign stack addresses.  */
 #define FLOATING_STACKS 1
 
diff -urN libc/linuxthreads/sysdeps/sparc/sparc32/pt-machine.h libc/linuxthreads/sysdeps/sparc/sparc32/pt-machine.h
--- libc/linuxthreads/sysdeps/sparc/sparc32/pt-machine.h	Wed Nov 14 09:47:09 2001
+++ libc/linuxthreads/sysdeps/sparc/sparc32/pt-machine.h	Wed Nov 14 09:43:58 2001
@@ -24,8 +24,8 @@
 #endif
 
 /* Spinlock implementation; required.  */
-PT_EI long int
-testandset (int *spinlock)
+PT_EI int
+try_lock (int *spinlock)
 {
   int ret;
 
@@ -36,6 +36,7 @@
   return ret;
 }
 
+#define lock_held(p) *(p)
 
 /* Memory barrier; default is to do nothing */
 #define MEMORY_BARRIER() __asm__ __volatile__("stbar" : : : "memory")
diff -urN libc/linuxthreads/sysdeps/sparc/sparc64/pt-machine.h libc/linuxthreads/sysdeps/sparc/sparc64/pt-machine.h
--- libc/linuxthreads/sysdeps/sparc/sparc64/pt-machine.h	Wed Nov 14 09:47:09 2001
+++ libc/linuxthreads/sysdeps/sparc/sparc64/pt-machine.h	Wed Nov 14 09:43:58 2001
@@ -25,8 +25,8 @@
 
 
 /* Spinlock implementation; required.  */
-PT_EI long int
-testandset (int *spinlock)
+PT_EI int
+try_lock (int *spinlock)
 {
   int ret;
 
@@ -36,6 +36,7 @@
   return ret;
 }
 
+#define lock_held(p) *(p)
 
 /* Memory barrier; default is to do nothing */
 #define MEMORY_BARRIER() \
diff -urN libc/linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/initspin.h libc/linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/initspin.h
--- libc/linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/initspin.h	Wed Nov 14 09:47:09 2001
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/initspin.h	Wed Nov 14 09:43:58 2001
@@ -19,9 +19,12 @@
 
 /* Initial value of a spinlock.  PA-RISC only implements atomic load
    and clear so this must be non-zero. */
-#define __LT_SPINLOCK_INIT 1
+#define __ATOMIC_LOCK_INIT  ((__atomic_lock_t) { 1 })
 
 /* Macros for lock initializers, using the above definition. */
-#define __LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT }
-#define __ALT_LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT }
-#define __ATOMIC_INITIALIZER { 0, __LT_SPINLOCK_INIT }
+#define __LOCK_INITIALIZER { { 1 }, 0 }
+#define __ATOMIC_INITIALIZER { 0, { 1 } }
+
+/* Tell the generic code it can't put locks in the bss section */
+
+#define __LOCK_INITIALISER_NOT_ZERO
diff -urN libc/linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/pthreadtypes.h libc/linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/pthreadtypes.h
--- libc/linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/pthreadtypes.h	Wed Dec 31 19:00:00 1969
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/pthreadtypes.h	Wed Nov 14 09:43:58 2001
@@ -0,0 +1,146 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/*                                                                      */
+/* This program is free software; you can redistribute it and/or        */
+/* modify it under the terms of the GNU Library General Public License  */
+/* as published by the Free Software Foundation; either version 2       */
+/* of the License, or (at your option) any later version.               */
+/*                                                                      */
+/* This program 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 Library General Public License for more details.                 */
+
+#if !defined _BITS_TYPES_H && !defined _PTHREAD_H
+# error "Never include <bits/pthreadtypes.h> directly; use <sys/types.h> instead."
+#endif
+
+#ifndef _BITS_PTHREADTYPES_H
+#define _BITS_PTHREADTYPES_H	1
+
+#define __need_schedparam
+#include <bits/sched.h>
+
+typedef struct {
+	int lock;
+} __attribute__((aligned (16))) __atomic_lock_t;
+
+/* Fast locks (not abstract because mutexes and conditions aren't abstract). */
+struct _pthread_fastlock
+{
+  __atomic_lock_t __spinlock;  /* Used by compare_and_swap emulation. Also,
+			  adaptive SMP lock stores spin count here. */
+  long int __status;   /* "Free" or "taken" or head of waiting list */
+};
+
+#ifndef _PTHREAD_DESCR_DEFINED
+/* Thread descriptors */
+typedef struct _pthread_descr_struct *_pthread_descr;
+# define _PTHREAD_DESCR_DEFINED
+#endif
+
+
+/* Attributes for threads.  */
+typedef struct __pthread_attr_s
+{
+  int __detachstate;
+  int __schedpolicy;
+  struct __sched_param __schedparam;
+  int __inheritsched;
+  int __scope;
+  size_t __guardsize;
+  int __stackaddr_set;
+  void *__stackaddr;
+  size_t __stacksize;
+} pthread_attr_t;
+
+
+/* Conditions (not abstract because of PTHREAD_COND_INITIALIZER */
+typedef struct
+{
+  struct _pthread_fastlock __c_lock; /* Protect against concurrent access */
+  _pthread_descr __c_waiting;        /* Threads waiting on this condition */
+} pthread_cond_t;
+
+
+/* Attribute for conditionally variables.  */
+typedef struct
+{
+  int __dummy;
+} pthread_condattr_t;
+
+/* Keys for thread-specific data */
+typedef unsigned int pthread_key_t;
+
+
+/* Mutexes (not abstract because of PTHREAD_MUTEX_INITIALIZER).  */
+/* (The layout is unnatural to maintain binary compatibility
+    with earlier releases of LinuxThreads.) */
+typedef struct
+{
+  int __m_reserved;               /* Reserved for future use */
+  int __m_count;                  /* Depth of recursive locking */
+  _pthread_descr __m_owner;       /* Owner thread (if recursive or errcheck) */
+  int __m_kind;                   /* Mutex kind: fast, recursive or errcheck */
+  struct _pthread_fastlock __m_lock; /* Underlying fast lock */
+} pthread_mutex_t;
+
+
+/* Attribute for mutex.  */
+typedef struct
+{
+  int __mutexkind;
+} pthread_mutexattr_t;
+
+
+/* Once-only execution */
+typedef int pthread_once_t;
+
+
+#ifdef __USE_UNIX98
+/* Read-write locks.  */
+typedef struct _pthread_rwlock_t
+{
+  struct _pthread_fastlock __rw_lock; /* Lock to guarantee mutual exclusion */
+  int __rw_readers;                   /* Number of readers */
+  _pthread_descr __rw_writer;         /* Identity of writer, or NULL if none */
+  _pthread_descr __rw_read_waiting;   /* Threads waiting for reading */
+  _pthread_descr __rw_write_waiting;  /* Threads waiting for writing */
+  int __rw_kind;                      /* Reader/Writer preference selection */
+  int __rw_pshared;                   /* Shared between processes or not */
+} pthread_rwlock_t;
+
+
+/* Attribute for read-write locks.  */
+typedef struct
+{
+  int __lockkind;
+  int __pshared;
+} pthread_rwlockattr_t;
+#endif
+
+#ifdef __USE_XOPEN2K
+/* POSIX spinlock data type.  */
+typedef volatile int pthread_spinlock_t __attribute__((aligned (16)));
+
+/* POSIX barrier. */
+typedef struct {
+  struct _pthread_fastlock __ba_lock; /* Lock to guarantee mutual exclusion */
+  int __ba_required;                  /* Threads needed for completion */
+  int __ba_present;                   /* Threads waiting */
+  _pthread_descr __ba_waiting;        /* Queue of waiting threads */
+} pthread_barrier_t;
+
+/* barrier attribute */
+typedef struct {
+  int __pshared;
+} pthread_barrierattr_t;
+
+#endif
+
+
+/* Thread identifiers */
+typedef unsigned long int pthread_t;
+
+#endif	/* bits/pthreadtypes.h */
diff -urN libc/sysdeps/hppa/dl-fptr.c libc/sysdeps/hppa/dl-fptr.c
--- libc/sysdeps/hppa/dl-fptr.c	Wed Nov 14 09:47:09 2001
+++ libc/sysdeps/hppa/dl-fptr.c	Wed Nov 14 09:43:58 2001
@@ -29,8 +29,7 @@
 #ifdef _LIBC_REENTRANT
 # include <pt-machine.h>
 
-/* Remember, we use 0 to mean that a lock is taken on PA-RISC. */
-static int __hppa_fptr_lock = 1;
+static __atomic_lock_t __hppa_fptr_lock = __ATOMIC_LOCK_INIT;
 #endif
 
 /* Because ld.so is now versioned, these functions can be in their own
@@ -66,7 +65,7 @@
 #ifdef _LIBC_REENTRANT
   /* Make sure we are alone. We don't need a lock during bootstrap. */
   if (mem == NULL)
-    while (testandset (&__hppa_fptr_lock));
+    while (try_lock(&__hppa_fptr_lock));
 #endif
 
   /* Search the sorted linked list for an existing entry for this
@@ -126,9 +125,8 @@
 
 found:
 #ifdef _LIBC_REENTRANT
-  /* Release the lock.  Again, remember, zero means the lock is taken!  */
   if (mem == NULL)
-    __hppa_fptr_lock = 1;
+    __hppa_fptr_lock = __ATOMIC_LOCK_INIT;
 #endif
 
   /* Set bit 30 to indicate to $$dyncall that this is a PLABEL. */
@@ -147,7 +145,7 @@
 
 #ifdef _LIBC_REENTRANT
   /* Make sure we are alone.  */
-  while (testandset (&__hppa_fptr_lock));
+  while (try_lock(&__hppa_fptr_lock));
 #endif
 
   /* Search the sorted linked list for the first entry for this object.  */
@@ -180,8 +178,7 @@
     }
 
 #ifdef _LIBC_REENTRANT
-  /* Release the lock. */
-  __hppa_fptr_lock = 1;
+  __hppa_fptr_lock = __ATOMIC_LOCK_INIT;
 #endif
 }
 
@@ -191,9 +188,11 @@
   Elf32_Addr addr = (Elf32_Addr) address;
   struct hppa_fptr *f;
 
+  address = (unsigned long)address &~ 3; /* Clear the bottom two bits.  See make_fptr. */
+
 #ifdef _LIBC_REENTRANT
   /* Make sure we are alone.  */
-  while (testandset (&__hppa_fptr_lock));
+  while (try_lock(&__hppa_fptr_lock));
 #endif
 
   for (f = __fptr_root; f != NULL; f = f->next)
@@ -204,8 +203,7 @@
       }
 
 #ifdef _LIBC_REENTRANT
-  /* Release the lock.   */
-  __hppa_fptr_lock = 1;
+  __hppa_fptr_lock = __ATOMIC_LOCK_INIT;
 #endif
 
   return addr;
diff -urN libc/sysdeps/ia64/dl-fptr.c libc/sysdeps/ia64/dl-fptr.c
--- libc/sysdeps/ia64/dl-fptr.c	Wed Nov 14 09:47:09 2001
+++ libc/sysdeps/ia64/dl-fptr.c	Wed Nov 14 09:43:58 2001
@@ -40,7 +40,7 @@
     struct ia64_fdesc *free_list;
     unsigned int npages;		/* # of pages to allocate */
 #ifdef _LIBC_REENTRANT
-    volatile int lock;
+    __atomic_lock_t lock;
     sigset_t full_sigset;
 #endif
     /* the next to members MUST be consecutive! */
@@ -73,7 +73,7 @@
   if (!__sigismember (&(l)->full_sigset, SIGINT))		\
     __sigfillset (&(l)->full_sigset);				\
 								\
-  while (testandset ((int *) &(l)->lock))			\
+  while (try_lock (&(l)->lock))					\
     {								\
       struct timespec ts;					\
       if (i > 0)						\
@@ -88,7 +88,7 @@
   __sigprocmask (SIG_BLOCK, &(l)->full_sigset, &_saved_set);
 # define unlock(l)						\
   __sigprocmask (SIG_SETMASK, &_saved_set, NULL);		\
-  (l)->lock = 0;						\
+  (l)->lock = __ATOMIC_LOCK_INIT;				\
 }
 #else
 # define lock(l)
diff -urN libc/sysdeps/unix/sysv/linux/hppa/bits/msq.h libc/sysdeps/unix/sysv/linux/hppa/bits/msq.h
--- libc/sysdeps/unix/sysv/linux/hppa/bits/ipc.h	Wed Dec 31 19:00:00 1969
+++ libc/sysdeps/unix/sysv/linux/hppa/bits/ipc.h	Mon Jul 23 19:57:52 2001
@@ -0,0 +1,63 @@
+/* Copyright (C) 1995-1999, 2000 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 _SYS_IPC_H
+# error "Never use <bits/ipc.h> directly; include <sys/ipc.h> instead."
+#endif
+
+#include <bits/types.h>
+#include <bits/wordsize.h>
+
+/* Mode bits for `msgget', `semget', and `shmget'.  */
+#define IPC_CREAT	01000		/* Create key if key does not exist. */
+#define IPC_EXCL	02000		/* Fail if key exists.  */
+#define IPC_NOWAIT	04000		/* Return error on wait.  */
+
+/* Control commands for `msgctl', `semctl', and `shmctl'.  */
+#define IPC_RMID	0		/* Remove identifier.  */
+#define IPC_SET		1		/* Set `ipc_perm' options.  */
+#define IPC_STAT	2		/* Get `ipc_perm' options.  */
+#ifdef __USE_GNU
+# define IPC_INFO	3		/* See ipcs.  */
+#endif
+
+/* Special key values.  */
+#define IPC_PRIVATE	((__key_t) 0)	/* Private key.  */
+
+
+/* Data structure used to pass permission information to IPC operations.  */
+struct ipc_perm
+  {
+    __key_t __key;			/* Key.  */
+    __uid_t uid;			/* Owner's user ID.  */
+    __gid_t gid;			/* Owner's group ID.  */
+    __uid_t cuid;			/* Creator's user ID.  */
+    __gid_t cgid;			/* Creator's group ID.  */
+#if __WORDSIZE == 32
+    unsigned short int __pad1;
+    unsigned short int mode;		/* Read/write permission.  */
+    unsigned short int __pad2;
+#else
+    __mode_t mode;			/* Read/write permission.  */
+    unsigned short int __pad2;
+#endif
+    unsigned short int __seq;		/* Sequence number.  */
+    unsigned int __pad3;
+    unsigned long long int __unused1;
+    unsigned long long int __unused2;
+  };
diff -urN libc/sysdeps/unix/sysv/linux/hppa/bits/msq.h libc/sysdeps/unix/sysv/linux/hppa/bits/msq.h
--- libc/sysdeps/unix/sysv/linux/hppa/bits/msq.h	Wed Dec 31 19:00:00 1969
+++ libc/sysdeps/unix/sysv/linux/hppa/bits/msq.h	Fri Nov 16 22:50:12 2001
@@ -0,0 +1,84 @@
+/* Copyright (C) 1995, 1996, 1997, 2000 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 _SYS_MSG_H
+# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
+#endif
+
+#include <bits/types.h>
+#include <bits/wordsize.h>
+
+/* Define options for message queue functions.  */
+#define MSG_NOERROR	010000	/* no error if message is too big */
+#ifdef __USE_GNU
+# define MSG_EXCEPT	020000	/* recv any msg except of specified type */
+#endif
+
+/* Types used in the structure definition.  */
+typedef unsigned long int msgqnum_t;
+typedef unsigned long int msglen_t;
+
+
+/* Structure of record for one message inside the kernel.
+   The type `struct msg' is opaque.  */
+struct msqid_ds
+{
+  struct ipc_perm msg_perm;	/* structure describing operation permission */
+#if __WORDSIZE == 32
+  unsigned int __pad1;
+#endif
+  __time_t msg_stime;		/* time of last msgsnd command */
+#if __WORDSIZE == 32
+  unsigned int __pad2;
+#endif
+  __time_t msg_rtime;		/* time of last msgrcv command */
+#if __WORDSIZE == 32
+  unsigned int __pad3;
+#endif
+  __time_t msg_ctime;		/* time of last change */
+  unsigned long int __msg_cbytes; /* current number of bytes on queue */
+  msgqnum_t msg_qnum;		/* number of messages currently on queue */
+  msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
+  __pid_t msg_lspid;		/* pid of last msgsnd() */
+  __pid_t msg_lrpid;		/* pid of last msgrcv() */
+  unsigned long int __unused1;
+  unsigned long int __unused2;
+};
+
+#ifdef __USE_MISC
+
+# define msg_cbytes	__msg_cbytes
+
+/* ipcs ctl commands */
+# define MSG_STAT 11
+# define MSG_INFO 12
+
+/* buffer for msgctl calls IPC_INFO, MSG_INFO */
+struct msginfo
+  {
+    int msgpool;
+    int msgmap;
+    int msgmax;
+    int msgmnb;
+    int msgmni;
+    int msgssz;
+    int msgtql;
+    unsigned short int msgseg;
+  };
+
+#endif /* __USE_MISC */
diff -urN libc/sysdeps/unix/sysv/linux/hppa/bits/sem.h libc/sysdeps/unix/sysv/linux/hppa/bits/sem.h
--- libc/sysdeps/unix/sysv/linux/hppa/bits/sem.h	Wed Dec 31 19:00:00 1969
+++ libc/sysdeps/unix/sysv/linux/hppa/bits/sem.h	Fri Nov 16 22:50:05 2001
@@ -0,0 +1,92 @@
+/* Copyright (C) 1995, 1996, 1997, 1998, 2000 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 _SYS_SEM_H
+# error "Never include <bits/sem.h> directly; use <sys/sem.h> instead."
+#endif
+
+#include <sys/types.h>
+#include <bits/wordsize.h>
+
+/* Flags for `semop'.  */
+#define SEM_UNDO	0x1000		/* undo the operation on exit */
+
+/* Commands for `semctl'.  */
+#define GETPID		11		/* get sempid */
+#define GETVAL		12		/* get semval */
+#define GETALL		13		/* get all semval's */
+#define GETNCNT		14		/* get semncnt */
+#define GETZCNT		15		/* get semzcnt */
+#define SETVAL		16		/* set semval */
+#define SETALL		17		/* set all semval's */
+
+
+/* Data structure describing a set of semaphores.  */
+struct semid_ds
+{
+  struct ipc_perm sem_perm;		/* operation permission struct */
+#if __WORDSIZE == 32
+  unsigned int __pad1;
+#endif
+  __time_t sem_otime;			/* last semop() time */
+#if __WORDSIZE == 32
+  unsigned int __pad2;
+#endif
+  __time_t sem_ctime;			/* last time changed by semctl() */
+  unsigned long int sem_nsems;		/* number of semaphores in set */
+  unsigned long int __unused1;
+  unsigned long int __unused2;
+};
+
+/* The user should define a union like the following to use it for arguments
+   for `semctl'.
+
+   union semun
+   {
+     int val;				<= value for SETVAL
+     struct semid_ds *buf;		<= buffer for IPC_STAT & IPC_SET
+     unsigned short int *array;		<= array for GETALL & SETALL
+     struct seminfo *__buf;		<= buffer for IPC_INFO
+   };
+
+   Previous versions of this file used to define this union but this is
+   incorrect.  One can test the macro _SEM_SEMUN_UNDEFINED to see whether
+   one must define the union or not.  */
+#define _SEM_SEMUN_UNDEFINED	1
+
+#ifdef __USE_MISC
+
+/* ipcs ctl cmds */
+# define SEM_STAT 18
+# define SEM_INFO 19
+
+struct  seminfo
+{
+  int semmap;
+  int semmni;
+  int semmns;
+  int semmnu;
+  int semmsl;
+  int semopm;
+  int semume;
+  int semusz;
+  int semvmx;
+  int semaem;
+};
+
+#endif /* __USE_MISC */
diff -urN libc/sysdeps/unix/sysv/linux/hppa/bits/shm.h libc/sysdeps/unix/sysv/linux/hppa/bits/shm.h
--- libc/sysdeps/unix/sysv/linux/hppa/bits/shm.h	Wed Dec 31 19:00:00 1969
+++ libc/sysdeps/unix/sysv/linux/hppa/bits/shm.h	Fri Nov 16 22:23:16 2001
@@ -0,0 +1,103 @@
+/* Copyright (C) 1995, 1996, 1997, 2000 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 _SYS_SHM_H
+# error "Never include <bits/shm.h> directly; use <sys/shm.h> instead."
+#endif
+
+#include <bits/types.h>
+#include <bits/wordsize.h>
+
+/* Permission flag for shmget.  */
+#define SHM_R		0400		/* or S_IRUGO from <linux/stat.h> */
+#define SHM_W		0200		/* or S_IWUGO from <linux/stat.h> */
+
+/* Flags for `shmat'.  */
+#define SHM_RDONLY	010000		/* attach read-only else read-write */
+#define SHM_RND		020000		/* round attach address to SHMLBA */
+#define SHM_REMAP	040000		/* take-over region on attach */
+
+/* Commands for `shmctl'.  */
+#define SHM_LOCK	11		/* lock segment (root only) */
+#define SHM_UNLOCK	12		/* unlock segment (root only) */
+
+
+/* Type to count number of attaches.  */
+typedef unsigned long int shmatt_t;
+
+/* Data structure describing a set of semaphores.  */
+struct shmid_ds
+  {
+    struct ipc_perm shm_perm;		/* operation permission struct */
+#if __WORDSIZE == 32
+    unsigned int __pad1;
+#endif
+    __time_t shm_atime;			/* time of last shmat() */
+#if __WORDSIZE == 32
+    unsigned int __pad2;
+#endif
+    __time_t shm_dtime;			/* time of last shmdt() */
+#if __WORDSIZE == 32
+    unsigned int __pad3;
+#endif
+    __time_t shm_ctime;			/* time of last change by shmctl() */
+#if __WORDSIZE == 32
+    unsigned int __pad4;
+#endif
+    size_t shm_segsz;			/* size of segment in bytes */
+    __pid_t shm_cpid;			/* pid of creator */
+    __pid_t shm_lpid;			/* pid of last shmop */
+    shmatt_t shm_nattch;		/* number of current attaches */
+    unsigned long int __unused1;
+    unsigned long int __unused2;
+  };
+
+#ifdef __USE_MISC
+
+/* ipcs ctl commands */
+# define SHM_STAT 	13
+# define SHM_INFO 	14
+
+/* shm_mode upper byte flags */
+# define SHM_DEST	01000	/* segment will be destroyed on last detach */
+# define SHM_LOCKED	02000   /* segment will not be swapped */
+
+struct	shminfo
+  {
+    unsigned long shmmax;
+    unsigned long shmmin;
+    unsigned long shmmni;
+    unsigned long shmseg;
+    unsigned long shmall;
+    unsigned long __unused1;
+    unsigned long __unused2;
+    unsigned long __unused3;
+    unsigned long __unused4;
+  };
+
+struct shm_info
+  {
+    int used_ids;
+    unsigned long int shm_tot;	/* total allocated shm */
+    unsigned long int shm_rss;	/* total resident shm */
+    unsigned long int shm_swp;	/* total swapped shm */
+    unsigned long int swap_attempts;
+    unsigned long int swap_successes;
+  };
+
+#endif /* __USE_MISC */

Reply to: