Browse Source

Revert "resolve merge"

This reverts commit 6b6ede3d15f04fe825cfa9f697507457e3640344.
Waldemar Brodkorb 9 years ago
parent
commit
e1e46622ac
100 changed files with 11535 additions and 20 deletions
  1. 1 1
      Makefile.in
  2. 3 1
      Rules.mak
  3. 30 7
      extra/Configs/Config.in
  4. 1 1
      extra/Configs/defconfigs/arc/tb10x_defconfig
  5. 2 2
      include/cancel.h
  6. 1 1
      libc/signal/allocrtsig.c
  7. 1 1
      libc/stdlib/malloc-standard/malloc.h
  8. 2 2
      libc/stdlib/malloc/malloc.h
  9. 1 1
      libc/sysdeps/linux/common/bits/uClibc_local_lim.h
  10. 17 0
      libc/sysdeps/linux/common/not-cancel.h
  11. 1 1
      libc/sysdeps/linux/common/pause.c
  12. 1 1
      libc/sysdeps/linux/common/pread_write.c
  13. 4 1
      libc/unistd/confstr.c
  14. 13 0
      libpthread/linuxthreads.old/Makefile
  15. 119 0
      libpthread/linuxthreads.old/Makefile.in
  16. 240 0
      libpthread/linuxthreads.old/attr.c
  17. 219 0
      libpthread/linuxthreads.old/cancel.c
  18. 304 0
      libpthread/linuxthreads.old/condvar.c
  19. 0 0
      libpthread/linuxthreads.old/debug.h
  20. 35 0
      libpthread/linuxthreads.old/errno.c
  21. 36 0
      libpthread/linuxthreads.old/events.c
  22. 173 0
      libpthread/linuxthreads.old/forward.c
  23. 529 0
      libpthread/linuxthreads.old/internals.h
  24. 231 0
      libpthread/linuxthreads.old/join.c
  25. 43 0
      libpthread/linuxthreads.old/libc_pthread_init.c
  26. 0 0
      libpthread/linuxthreads.old/linuxthreads.texi
  27. 0 0
      libpthread/linuxthreads.old/locale.c
  28. 42 0
      libpthread/linuxthreads.old/lockfile.c
  29. 933 0
      libpthread/linuxthreads.old/manager.c
  30. 362 0
      libpthread/linuxthreads.old/mutex.c
  31. 21 0
      libpthread/linuxthreads.old/pt-machine.c
  32. 167 0
      libpthread/linuxthreads.old/ptfork.c
  33. 1165 0
      libpthread/linuxthreads.old/pthread.c
  34. 0 0
      libpthread/linuxthreads.old/ptlongjmp.c
  35. 60 0
      libpthread/linuxthreads.old/queue.h
  36. 50 0
      libpthread/linuxthreads.old/restart.h
  37. 485 0
      libpthread/linuxthreads.old/rwlock.c
  38. 299 0
      libpthread/linuxthreads.old/semaphore.c
  39. 97 0
      libpthread/linuxthreads.old/semaphore.h
  40. 246 0
      libpthread/linuxthreads.old/signals.c
  41. 198 0
      libpthread/linuxthreads.old/specific.c
  42. 720 0
      libpthread/linuxthreads.old/spinlock.c
  43. 218 0
      libpthread/linuxthreads.old/spinlock.h
  44. 126 0
      libpthread/linuxthreads.old/sysdeps/alpha/pt-machine.h
  45. 0 0
      libpthread/linuxthreads.old/sysdeps/arc/pt-machine.h
  46. 110 0
      libpthread/linuxthreads.old/sysdeps/arm/pt-machine.h
  47. 73 0
      libpthread/linuxthreads.old/sysdeps/avr32/pt-machine.h
  48. 0 0
      libpthread/linuxthreads.old/sysdeps/bfin/pt-machine.h
  49. 0 0
      libpthread/linuxthreads.old/sysdeps/c6x/pt-machine.h
  50. 69 0
      libpthread/linuxthreads.old/sysdeps/cris/pt-machine.h
  51. 0 0
      libpthread/linuxthreads.old/sysdeps/frv/pt-machine.h
  52. 0 0
      libpthread/linuxthreads.old/sysdeps/h8300/pt-machine.h
  53. 146 0
      libpthread/linuxthreads.old/sysdeps/i386/pt-machine.h
  54. 184 0
      libpthread/linuxthreads.old/sysdeps/i386/tls.h
  55. 306 0
      libpthread/linuxthreads.old/sysdeps/i386/useldt.h
  56. 134 0
      libpthread/linuxthreads.old/sysdeps/ia64/pt-machine.h
  57. 138 0
      libpthread/linuxthreads.old/sysdeps/ia64/tls.h
  58. 74 0
      libpthread/linuxthreads.old/sysdeps/m68k/pt-machine.h
  59. 0 0
      libpthread/linuxthreads.old/sysdeps/microblaze/pt-machine.h
  60. 0 0
      libpthread/linuxthreads.old/sysdeps/microblaze/sigcontextinfo.h
  61. 105 0
      libpthread/linuxthreads.old/sysdeps/mips/pt-machine.h
  62. 0 0
      libpthread/linuxthreads.old/sysdeps/nios/pt-machine.h
  63. 0 0
      libpthread/linuxthreads.old/sysdeps/nios2/pt-machine.h
  64. 101 0
      libpthread/linuxthreads.old/sysdeps/powerpc/pt-machine.h
  65. 415 0
      libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-lock.h
  66. 69 0
      libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-tsd.h
  67. 145 0
      libpthread/linuxthreads.old/sysdeps/pthread/bits/pthreadtypes.h
  68. 113 0
      libpthread/linuxthreads.old/sysdeps/pthread/not-cancel.h
  69. 113 0
      libpthread/linuxthreads.old/sysdeps/pthread/pthread-functions.h
  70. 710 0
      libpthread/linuxthreads.old/sysdeps/pthread/pthread.h
  71. 0 0
      libpthread/linuxthreads.old/sysdeps/pthread/tls.h
  72. 81 0
      libpthread/linuxthreads.old/sysdeps/sh/pt-machine.h
  73. 116 0
      libpthread/linuxthreads.old/sysdeps/sh/tls.h
  74. 0 0
      libpthread/linuxthreads.old/sysdeps/sh64/Makefile.arch
  75. 0 0
      libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.c
  76. 0 0
      libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.h
  77. 82 0
      libpthread/linuxthreads.old/sysdeps/sparc/pt-machine.h
  78. 0 0
      libpthread/linuxthreads.old/sysdeps/sparc/tcb-offsets.h
  79. 0 0
      libpthread/linuxthreads.old/sysdeps/v850/pt-machine.h
  80. 87 0
      libpthread/linuxthreads.old/sysdeps/x86_64/pt-machine.h
  81. 133 0
      libpthread/linuxthreads.old/sysdeps/x86_64/tls.h
  82. 0 0
      libpthread/linuxthreads.old/sysdeps/xtensa/pt-machine.h
  83. 0 0
      libpthread/linuxthreads.old/wrapsyscall.c
  84. 1 0
      libpthread/linuxthreads.old_db/Banner
  85. 13 0
      libpthread/linuxthreads.old_db/Makefile
  86. 78 0
      libpthread/linuxthreads.old_db/Makefile.in
  87. 24 0
      libpthread/linuxthreads.old_db/Versions
  88. 69 0
      libpthread/linuxthreads.old_db/proc_service.h
  89. 32 0
      libpthread/linuxthreads.old_db/td_init.c
  90. 31 0
      libpthread/linuxthreads.old_db/td_log.c
  91. 60 0
      libpthread/linuxthreads.old_db/td_symbol_list.c
  92. 50 0
      libpthread/linuxthreads.old_db/td_ta_clear_event.c
  93. 57 0
      libpthread/linuxthreads.old_db/td_ta_delete.c
  94. 34 0
      libpthread/linuxthreads.old_db/td_ta_enable_stats.c
  95. 72 0
      libpthread/linuxthreads.old_db/td_ta_event_addr.c
  96. 127 0
      libpthread/linuxthreads.old_db/td_ta_event_getmsg.c
  97. 41 0
      libpthread/linuxthreads.old_db/td_ta_get_nthreads.c
  98. 35 0
      libpthread/linuxthreads.old_db/td_ta_get_ph.c
  99. 34 0
      libpthread/linuxthreads.old_db/td_ta_get_stats.c
  100. 77 0
      libpthread/linuxthreads.old_db/td_ta_map_id2thr.c

+ 1 - 1
Makefile.in

@@ -385,7 +385,7 @@ else
 endif
 endif
 	echo "$(UBACKTRACE_ASNEEDED)" >> $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR)/libc.so
 	echo "$(UBACKTRACE_ASNEEDED)" >> $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR)/libc.so
 ifeq ($(UCLIBC_HAS_THREADS),y)
 ifeq ($(UCLIBC_HAS_THREADS),y)
-ifneq ($(UCLIBC_HAS_LINUXTHREADS),y)
+ifneq ($(LINUXTHREADS_OLD),y)
 ifeq ($(HARDWIRED_ABSPATH),y)
 ifeq ($(HARDWIRED_ABSPATH),y)
 	if [ -f $(top_builddir)lib/libpthread.so -a -f $(PREFIX)$(RUNTIME_PREFIX)$(MULTILIB_DIR)/libpthread.so.$(ABI_VERSION) ] ; then \
 	if [ -f $(top_builddir)lib/libpthread.so -a -f $(PREFIX)$(RUNTIME_PREFIX)$(MULTILIB_DIR)/libpthread.so.$(ABI_VERSION) ] ; then \
 		$(RM) $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR)/libpthread.so; \
 		$(RM) $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR)/libpthread.so; \

+ 3 - 1
Rules.mak

@@ -723,7 +723,9 @@ ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y)
 	PTNAME := nptl
 	PTNAME := nptl
 	CFLAGS += -DHAVE_FORCED_UNWIND -D_LIBC_REENTRANT
 	CFLAGS += -DHAVE_FORCED_UNWIND -D_LIBC_REENTRANT
 else
 else
-ifeq ($(UCLIBC_HAS_LINUXTHREADS),y)
+ifeq ($(LINUXTHREADS_OLD),y)
+	PTNAME := linuxthreads.old
+else
 	PTNAME := linuxthreads
 	PTNAME := linuxthreads
 endif
 endif
 endif
 endif

+ 30 - 7
extra/Configs/Config.in

@@ -3,7 +3,7 @@
 # see extra/config/Kconfig-language.txt
 # see extra/config/Kconfig-language.txt
 #
 #
 
 
-mainmenu "uClibc-ng $VERSION C Library Configuration"
+mainmenu "uClibc $VERSION C Library Configuration"
 
 
 config DESIRED_TARGET_ARCH
 config DESIRED_TARGET_ARCH
 	string
 	string
@@ -506,6 +506,7 @@ config LDSO_GNU_HASH_SUPPORT
 
 
 choice
 choice
 	prompt "Thread support"
 	prompt "Thread support"
+	#default UCLIBC_HAS_THREADS_NATIVE if (TARGET_alpha || TARGET_arm || TARGET_i386 || TARGET_mips || TARGET_powerpc || TARGET_sh || TARGET_sh64)
 	default HAS_NO_THREADS
 	default HAS_NO_THREADS
 	help
 	help
 	  If you want to compile uClibc with pthread support, then answer Y.
 	  If you want to compile uClibc with pthread support, then answer Y.
@@ -518,9 +519,9 @@ config HAS_NO_THREADS
 	help
 	help
 	  Disable thread support.
 	  Disable thread support.
 
 
-config UCLIBC_HAS_LINUXTHREADS
-	bool "Enable support for linuxthreads"
-	# linuxthreads need nanosleep()
+config LINUXTHREADS_OLD
+	bool "older (stable) version of linuxthreads"
+	# linuxthreads and linuxthreads.old need nanosleep()
 	select UCLIBC_HAS_REALTIME
 	select UCLIBC_HAS_REALTIME
 	depends on !TARGET_arc && \
 	depends on !TARGET_arc && \
 		   !TARGET_i386 && \
 		   !TARGET_i386 && \
@@ -532,8 +533,29 @@ config UCLIBC_HAS_LINUXTHREADS
 		   !TARGET_x86_64 && \
 		   !TARGET_x86_64 && \
 		   !TARGET_xtensa
 		   !TARGET_xtensa
 	help
 	help
-	  See here for information about linuxthreads:
-	  http://en.wikipedia.org/wiki/LinuxThreads
+	  There are two versions of linuxthreads.  The older (stable) version
+	  has been in uClibc for quite a long time but hasn't seen too many
+	  updates other than bugfixes.
+
+
+config LINUXTHREADS_NEW
+	bool "slightly newer version of linuxthreads"
+	depends on ARCH_HAS_DEPRECATED_SYSCALLS
+	depends on !TARGET_arc && \
+		   !TARGET_arm && \
+		   !TARGET_i386 && \
+		   !TARGET_metag && \
+		   !TARGET_mips && \
+		   !TARGET_powerpc && \
+		   !TARGET_sh && \
+		   !TARGET_sparc && \
+		   !TARGET_x86_64 && \
+		   !TARGET_xtensa
+	help
+	  The new version has not been tested much, and lacks ports for arches
+	  which glibc does not support (like bfin/frv/etc...), but is based on
+	  the latest code from glibc, so it may be the only choice for the
+	  newer ports (like alpha/amd64/64bit arches and hppa).
 
 
 config UCLIBC_HAS_THREADS_NATIVE
 config UCLIBC_HAS_THREADS_NATIVE
 	bool "Native POSIX Threading (NPTL)"
 	bool "Native POSIX Threading (NPTL)"
@@ -586,6 +608,7 @@ config PTHREADS_DEBUG_SUPPORT
 	  If you are doing development and want to debug applications using
 	  If you are doing development and want to debug applications using
 	  uClibc's pthread library, answer Y.  Otherwise, answer N.
 	  uClibc's pthread library, answer Y.  Otherwise, answer N.
 
 
+
 config UCLIBC_HAS_SYSLOG
 config UCLIBC_HAS_SYSLOG
 	bool "Syslog support"
 	bool "Syslog support"
 	default y
 	default y
@@ -2333,7 +2356,7 @@ config DODEBUG
 
 
 config DODEBUG_PT
 config DODEBUG_PT
 	bool "Build pthread with debugging output"
 	bool "Build pthread with debugging output"
-	depends on UCLIBC_HAS_THREADS && UCLIBC_HAS_LINUXTHREADS
+	depends on UCLIBC_HAS_THREADS && LINUXTHREADS_OLD
 	help
 	help
 	  Enable debug output in libpthread.  This is only useful when doing
 	  Enable debug output in libpthread.  This is only useful when doing
 	  development in libpthread itself.
 	  development in libpthread itself.

+ 1 - 1
extra/Configs/defconfigs/arc/tb10x_defconfig

@@ -6,7 +6,7 @@ KERNEL_HEADERS="%KERNEL_HEADERS%"
 # LDSO_CACHE_SUPPORT is not set
 # LDSO_CACHE_SUPPORT is not set
 LDSO_RUNPATH=y
 LDSO_RUNPATH=y
 # LDSO_SAFE_RUNPATH is not set
 # LDSO_SAFE_RUNPATH is not set
-UCLIBC_HAS_LINUXTHREADS=y
+LINUXTHREADS_OLD=y
 PTHREADS_DEBUG_SUPPORT=y
 PTHREADS_DEBUG_SUPPORT=y
 MALLOC_GLIBC_COMPAT=y
 MALLOC_GLIBC_COMPAT=y
 UCLIBC_SUSV3_LEGACY=y
 UCLIBC_SUSV3_LEGACY=y

+ 2 - 2
include/cancel.h

@@ -48,7 +48,7 @@
 #define __NC_PROTO(name) extern __typeof(name) __NC(name) attribute_hidden;
 #define __NC_PROTO(name) extern __typeof(name) __NC(name) attribute_hidden;
 #define __NC_OLD_PROTO(name) extern __typeof(name) __NC_OLD(name);
 #define __NC_OLD_PROTO(name) extern __typeof(name) __NC_OLD(name);
 
 
-#if defined __UCLIBC_HAS_THREADS__ && !defined __UCLIBC_HAS_LINUXTHREADS__
+#if defined __UCLIBC_HAS_THREADS__ && !defined __LINUXTHREADS_OLD__
 # define __NEW_THREADS 1
 # define __NEW_THREADS 1
 #else
 #else
 # define SINGLE_THREAD_P 1
 # define SINGLE_THREAD_P 1
@@ -71,7 +71,7 @@ res_type weak_function name param_list					\
 # define lt_strong_alias(name)
 # define lt_strong_alias(name)
 # define lt_libc_hidden(name) libc_hidden_def(name)
 # define lt_libc_hidden(name) libc_hidden_def(name)
 
 
-#elif defined __UCLIBC_HAS_LINUXTHREADS__
+#elif defined __LINUXTHREADS_OLD__
 
 
 # define CANCELLABLE_SYSCALL(res_type, name, param_list, params)	\
 # define CANCELLABLE_SYSCALL(res_type, name, param_list, params)	\
 weak_alias(__NC(name),name)						\
 weak_alias(__NC(name),name)						\

+ 1 - 1
libc/signal/allocrtsig.c

@@ -32,7 +32,7 @@ static int current_rtmax = -1;
 #else
 #else
 # ifdef __UCLIBC_HAS_THREADS_NATIVE__
 # ifdef __UCLIBC_HAS_THREADS_NATIVE__
 static int current_rtmin = __SIGRTMIN + 2;
 static int current_rtmin = __SIGRTMIN + 2;
-# elif defined __UCLIBC_HAS_THREADS__ && !defined __UCLIBC_HAS_LINUXTHREADS__
+# elif defined __UCLIBC_HAS_THREADS__ && !defined __LINUXTHREADS_OLD__
 /* psm: might be good for LT old as well, do not want to break it for now */
 /* psm: might be good for LT old as well, do not want to break it for now */
 /* Sanity check */
 /* Sanity check */
 #  if !defined __SIGRTMIN || (__SIGRTMAX - __SIGRTMIN) < 3
 #  if !defined __SIGRTMIN || (__SIGRTMAX - __SIGRTMIN) < 3

+ 1 - 1
libc/stdlib/malloc-standard/malloc.h

@@ -27,7 +27,7 @@
 
 
 
 
 __UCLIBC_MUTEX_EXTERN(__malloc_lock)
 __UCLIBC_MUTEX_EXTERN(__malloc_lock)
-#if defined __UCLIBC_HAS_THREADS__ && !defined __UCLIBC_HAS_LINUXTHREADS__
+#if defined __UCLIBC_HAS_THREADS__ && !defined __LINUXTHREADS_OLD__
 	attribute_hidden
 	attribute_hidden
 #endif
 #endif
 	;
 	;

+ 2 - 2
libc/stdlib/malloc/malloc.h

@@ -199,13 +199,13 @@ extern void __malloc_debug_printf (int indent, const char *fmt, ...) attribute_h
 extern struct heap_free_area *__malloc_heap attribute_hidden;
 extern struct heap_free_area *__malloc_heap attribute_hidden;
 #ifdef __UCLIBC_HAS_THREADS__
 #ifdef __UCLIBC_HAS_THREADS__
 __UCLIBC_MUTEX_EXTERN(__malloc_heap_lock)
 __UCLIBC_MUTEX_EXTERN(__malloc_heap_lock)
-# ifndef __UCLIBC_HAS_LINUXTHREADS__
+# ifndef __LINUXTHREADS_OLD__
 	attribute_hidden
 	attribute_hidden
 # endif
 # endif
 	;
 	;
 # ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__
 # ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__
 __UCLIBC_MUTEX_EXTERN(__malloc_mmb_heap_lock)
 __UCLIBC_MUTEX_EXTERN(__malloc_mmb_heap_lock)
-#  ifndef __UCLIBC_HAS_LINUXTHREADS__
+#  ifndef __LINUXTHREADS_OLD__
 	attribute_hidden
 	attribute_hidden
 #  endif
 #  endif
 	;
 	;

+ 1 - 1
libc/sysdeps/linux/common/bits/uClibc_local_lim.h

@@ -20,7 +20,7 @@
 /* glibc uses 16384 */
 /* glibc uses 16384 */
 # define PTHREAD_THREADS_MAX	1024
 # define PTHREAD_THREADS_MAX	1024
 # define TIMER_MAX		256
 # define TIMER_MAX		256
-# ifdef __UCLIBC_HAS_LINUXTHREADS__
+# ifdef __LINUXTHREADS_OLD__
 #  undef SEM_VALUE_MAX
 #  undef SEM_VALUE_MAX
 #  define SEM_VALUE_MAX	((int) ((~0u) >> 1))
 #  define SEM_VALUE_MAX	((int) ((~0u) >> 1))
 # endif
 # endif

+ 17 - 0
libc/sysdeps/linux/common/not-cancel.h

@@ -70,6 +70,12 @@ extern int __openat64_nocancel (int fd, const char *fname, int oflag,
 #define read_not_cancel(fd, buf, n) \
 #define read_not_cancel(fd, buf, n) \
   INLINE_SYSCALL (read, 3, (fd), (buf), (n))
   INLINE_SYSCALL (read, 3, (fd), (buf), (n))
 
 
+#ifdef __LINUXTHREADS_NEW__
+/* Uncancelable write.  */
+#define write_not_cancel(fd, buf, n) \
+  INLINE_SYSCALL (write, 3, (fd), (buf), (n))
+#endif
+
 #if 0
 #if 0
 /* Uncancelable writev.  */
 /* Uncancelable writev.  */
 #define writev_not_cancel_no_status(fd, iov, n) \
 #define writev_not_cancel_no_status(fd, iov, n) \
@@ -81,6 +87,17 @@ extern int __openat64_nocancel (int fd, const char *fname, int oflag,
   __fcntl_nocancel (fd, cmd, val)
   __fcntl_nocancel (fd, cmd, val)
 #endif
 #endif
 
 
+#ifdef __LINUXTHREADS_NEW__
+/* Uncancelable waitpid.  */
+#if 0 /*def __NR_waitpid*/
+# define waitpid_not_cancel(pid, stat_loc, options) \
+  INLINE_SYSCALL (waitpid, 3, pid, stat_loc, options)
+#else
+# define waitpid_not_cancel(pid, stat_loc, options) \
+  INLINE_SYSCALL (wait4, 4, pid, stat_loc, options, NULL)
+#endif
+#endif
+
 /* Uncancelable pause.  */
 /* Uncancelable pause.  */
 #ifdef __NR_pause
 #ifdef __NR_pause
 # define pause_not_cancel() \
 # define pause_not_cancel() \

+ 1 - 1
libc/sysdeps/linux/common/pause.c

@@ -22,7 +22,7 @@ CANCELLABLE_SYSCALL(int, pause, (void), ())
 # include <signal.h>
 # include <signal.h>
 
 
 int
 int
-# ifdef __UCLIBC_HAS_LINUXTHREADS__
+# ifdef __LINUXTHREADS_OLD__
 weak_function
 weak_function
 # endif
 # endif
 __NC(pause)(void)
 __NC(pause)(void)

+ 1 - 1
libc/sysdeps/linux/common/pread_write.c

@@ -102,7 +102,7 @@ static ssize_t __NC(pwrite64)(int fd, const void *buf, size_t count, off64_t off
 CANCELLABLE_SYSCALL(ssize_t, pwrite64, (int fd, const void *buf, size_t count, off64_t offset),
 CANCELLABLE_SYSCALL(ssize_t, pwrite64, (int fd, const void *buf, size_t count, off64_t offset),
 		    (fd, buf, count, offset))
 		    (fd, buf, count, offset))
 # else
 # else
-#  ifdef __UCLIBC_HAS_LINUXTHREADS__
+#  ifdef __LINUXTHREADS_OLD__
 weak_alias(pread,pread64)
 weak_alias(pread,pread64)
 weak_alias(pwrite,pwrite64)
 weak_alias(pwrite,pwrite64)
 lt_strong_alias(pread64)
 lt_strong_alias(pread64)

+ 4 - 1
libc/unistd/confstr.c

@@ -43,9 +43,12 @@ size_t confstr (int name, char *buf, size_t len)
       break;
       break;
 #ifdef __UCLIBC_HAS_THREADS__
 #ifdef __UCLIBC_HAS_THREADS__
     case _CS_GNU_LIBPTHREAD_VERSION:
     case _CS_GNU_LIBPTHREAD_VERSION:
-# if defined __UCLIBC_HAS_LINUXTHREADS__
+# if defined __LINUXTHREADS_OLD__
       string = "linuxthreads-0.01";
       string = "linuxthreads-0.01";
       string_len = sizeof("linuxthreads-x.xx");
       string_len = sizeof("linuxthreads-x.xx");
+# elif defined __LINUXTHREADS_NEW__
+      string = "linuxthreads-0.10";
+      string_len = sizeof("linuxthreads-x.xx");
 # elif defined __UCLIBC_HAS_THREADS_NATIVE__
 # elif defined __UCLIBC_HAS_THREADS_NATIVE__
 #  define __NPTL_VERSION ("NPTL " \
 #  define __NPTL_VERSION ("NPTL " \
 		__stringify(__UCLIBC_MAJOR__) "." \
 		__stringify(__UCLIBC_MAJOR__) "." \

+ 13 - 0
libpthread/linuxthreads.old/Makefile

@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../
+top_builddir=../../
+include $(top_builddir)Rules.mak
+all: libs
+include Makefile.in
+include $(top_srcdir)Makerules

+ 119 - 0
libpthread/linuxthreads.old/Makefile.in

@@ -0,0 +1,119 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2003 Paul Mundt <lethal@linux-sh.org>
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libpthread/linuxthreads.old
+
+CFLAGS-dir_linuxthreads.old := -DNOT_IN_libc -DIS_IN_libpthread
+CFLAGS-libpthread/linuxthreads.old := $(CFLAGS-dir_linuxthreads.old) $(SSP_ALL_CFLAGS)
+
+ifeq ($(PTHREADS_DEBUG_SUPPORT),y)
+LDFLAGS-libpthread.so := $(LDFLAGS_NOSTRIP) -Wl,-z,defs
+else
+LDFLAGS-libpthread.so := $(LDFLAGS)
+endif
+LDFLAGS-$(UCLIBC_FORMAT_DSBT_ELF)-libpthread.so := -Wl,--dsbt-index=10
+
+LIBS-libpthread.so := $(LIBS) $(ldso)
+
+START_FILE-libpthread.so := $(SHARED_START_FILES)
+END_FILE-libpthread.so := $(SHARED_END_FILES)
+
+libpthread_FULL_NAME := libpthread-$(VERSION).so
+
+libpthread_DIR := $(top_srcdir)libpthread/linuxthreads.old
+libpthread_OUT := $(top_builddir)libpthread/linuxthreads.old
+
+-include $(libpthread_DIR)/sysdeps/$(TARGET_ARCH)/Makefile.arch
+
+libpthread_SRC := \
+	attr.c cancel.c condvar.c errno.c events.c join.c lockfile.c manager.c \
+	mutex.c pt-machine.c ptfork.c pthread.c ptlongjmp.c \
+	rwlock.c semaphore.c signals.c specific.c spinlock.c wrapsyscall.c
+ifeq ($(UCLIBC_HAS_XLOCALE),y)
+libpthread_SRC += locale.c
+endif
+
+# remove generic sources, if arch specific version is present
+ifneq ($(strip $(libpthread_ARCH_SRC)),)
+libpthread_SRC := $(filter-out $(patsubst %.c,$(libpthread_DIR)/%.c,$(notdir $(libpthread_ARCH_SRC))),$(libpthread_SRC))
+endif
+
+libpthread_SRC := $(patsubst %,$(libpthread_DIR)/%,$(libpthread_SRC))
+
+libpthread_OBJ := $(patsubst $(libpthread_DIR)/%.c,$(libpthread_OUT)/%.o,$(libpthread_SRC))
+
+#
+# Stuff that goes into libc.so, not libpthread.so
+#
+CFLAGS-OMIT-forward.c := $(CFLAGS-dir_linuxthreads.old)
+CFLAGS-OMIT-libc_pthread_init.c := $(CFLAGS-dir_linuxthreads.old)
+libpthread_libc_CSRC := forward.c libc_pthread_init.c
+libpthread_libc_OBJ  := $(patsubst %.c, $(libpthread_OUT)/%.o,$(libpthread_libc_CSRC))
+libc-static-y += $(libpthread_OUT)/libc_pthread_init.o
+libc-shared-y += $(libpthread_libc_OBJ:.o=.oS)
+
+ifeq ($(DOPIC),y)
+libpthread-a-y  += $(libpthread_OBJ:.o=.os)
+else
+libpthread-a-y  += $(libpthread_OBJ)
+endif
+libpthread-so-y += $(libpthread_OBJ:.o=.oS)
+
+lib-a-$(UCLIBC_HAS_THREADS) += $(top_builddir)lib/libpthread.a
+lib-so-$(UCLIBC_HAS_THREADS) += $(top_builddir)lib/libpthread.so
+
+#ifeq ($(DOMULTI),n)
+$(top_builddir)lib/libpthread.so: $(libpthread_OUT)/libpthread_so.a $(libc.depend)
+	$(call link.so,$(libpthread_FULL_NAME),$(ABI_VERSION))
+#else
+#$(top_builddir)lib/libpthread.so: $(libpthread_OUT)/libpthread.oS | $(libc.depend)
+#	$(call linkm.so,$(libpthread_FULL_NAME),$(ABI_VERSION))
+#endif
+
+ifeq ($(PTHREADS_DEBUG_SUPPORT),y)
+$(libpthread_OUT)/libpthread_so.a: STRIP_FLAGS:=$(STRIP_FLAGS:-x=-X --strip-debug)
+endif
+$(libpthread_OUT)/libpthread_so.a: $(libpthread-so-y)
+	$(Q)$(RM) $@
+	$(do_ar)
+
+ifeq ($(PTHREADS_DEBUG_SUPPORT),y)
+$(libpthread_OUT)/libpthread.oS: STRIP_FLAGS:=$(STRIP_FLAGS:-x=-X --strip-debug)
+endif
+$(libpthread_OUT)/libpthread.oS: $(libpthread_SRC)
+	$(Q)$(RM) $@
+	$(compile-m)
+
+ifeq ($(PTHREADS_DEBUG_SUPPORT),y)
+$(top_builddir)lib/libpthread.a: STRIP_FLAGS:=$(STRIP_FLAGS:-x=-X --strip-debug)
+endif
+$(top_builddir)lib/libpthread.a: $(libpthread-a-y)
+	$(Q)$(INSTALL) -d $(dir $@)
+	$(Q)$(RM) $@
+	$(do_ar)
+
+$(top_builddir)include/pthread.h:
+	$(do_ln) $(call rel_srcdir)$(PTDIR)/sysdeps/pthread/$(@F) $@
+$(top_builddir)include/semaphore.h:
+	$(do_ln) $(call rel_srcdir)$(PTDIR)/$(@F) $@
+$(top_builddir)include/bits/pthreadtypes.h: | $(top_builddir)include/bits
+	$(do_ln) $(call rel_srcdir)$(PTDIR)/sysdeps/pthread/bits/$(@F) $@
+
+linuxthreads_headers := $(top_builddir)include/pthread.h \
+			$(top_builddir)include/semaphore.h \
+			$(top_builddir)include/bits/pthreadtypes.h
+$(linuxthreads_headers): $(wildcard $(addprefix $(top_builddir)include/config/linuxthreads/,old.h new.h))
+headers-$(UCLIBC_HAS_THREADS) += $(linuxthreads_headers)
+
+objclean-y += CLEAN_libpthread/linuxthreads.old
+headers_clean-y += HEADERCLEAN_libpthread/linuxthreads.old
+HEADERCLEAN_libpthread/linuxthreads.old:
+	$(do_rm) $(linuxthreads_headers)
+
+CLEAN_libpthread/linuxthreads.old:
+	$(do_rm) $(addprefix $(libpthread_OUT)/*., o os oS a)

+ 240 - 0
libpthread/linuxthreads.old/attr.c

@@ -0,0 +1,240 @@
+/* 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.                 */
+
+/* changed for uClibc */
+#define __sched_get_priority_min sched_get_priority_min
+#define __sched_get_priority_max sched_get_priority_max
+
+/* Handling of thread attributes */
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include "pthread.h"
+#include "internals.h"
+
+libpthread_hidden_proto(pthread_attr_destroy)
+libpthread_hidden_proto(pthread_attr_init)
+libpthread_hidden_proto(pthread_attr_getdetachstate)
+libpthread_hidden_proto(pthread_attr_setdetachstate)
+libpthread_hidden_proto(pthread_attr_getinheritsched)
+libpthread_hidden_proto(pthread_attr_setinheritsched)
+libpthread_hidden_proto(pthread_attr_setschedparam)
+libpthread_hidden_proto(pthread_attr_getschedparam)
+libpthread_hidden_proto(pthread_attr_getschedpolicy)
+libpthread_hidden_proto(pthread_attr_setschedpolicy)
+libpthread_hidden_proto(pthread_attr_getscope)
+libpthread_hidden_proto(pthread_attr_setscope)
+
+/* NOTE: With uClibc I don't think we need this versioning stuff.
+ * Therefore, define the function pthread_attr_init() here using
+ * a strong symbol. */
+
+/*int __pthread_attr_init_2_1(pthread_attr_t *attr)*/
+int pthread_attr_init(pthread_attr_t *attr)
+{
+  size_t ps = getpagesize ();
+
+  attr->__detachstate = PTHREAD_CREATE_JOINABLE;
+  attr->__schedpolicy = SCHED_OTHER;
+  attr->__schedparam.sched_priority = 0;
+  attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
+  attr->__scope = PTHREAD_SCOPE_SYSTEM;
+  attr->__guardsize = ps;
+  attr->__stackaddr = NULL;
+  attr->__stackaddr_set = 0;
+  attr->__stacksize = STACK_SIZE - ps;
+  return 0;
+}
+libpthread_hidden_def(pthread_attr_init)
+
+/* uClibc: leave out this for now. */
+#if defined DO_PTHREAD_VERSIONING_WITH_UCLIBC
+#if defined __PIC__ && defined DO_VERSIONING
+default_symbol_version (__pthread_attr_init_2_1, pthread_attr_init, GLIBC_2.1);
+
+int __pthread_attr_init_2_0(pthread_attr_t *attr)
+{
+  attr->__detachstate = PTHREAD_CREATE_JOINABLE;
+  attr->__schedpolicy = SCHED_OTHER;
+  attr->__schedparam.sched_priority = 0;
+  attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
+  attr->__scope = PTHREAD_SCOPE_SYSTEM;
+  return 0;
+}
+symbol_version (__pthread_attr_init_2_0, pthread_attr_init, GLIBC_2.0);
+#else
+strong_alias (__pthread_attr_init_2_1, pthread_attr_init)
+#endif
+#endif /* DO_PTHREAD_VERSIONING_WITH_UCLIBC */
+
+int pthread_attr_destroy(pthread_attr_t *attr attribute_unused)
+{
+  return 0;
+}
+libpthread_hidden_def(pthread_attr_destroy)
+
+
+int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
+{
+  if (detachstate < PTHREAD_CREATE_JOINABLE ||
+      detachstate > PTHREAD_CREATE_DETACHED)
+    return EINVAL;
+  attr->__detachstate = detachstate;
+  return 0;
+}
+libpthread_hidden_def(pthread_attr_setdetachstate)
+
+int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
+{
+  *detachstate = attr->__detachstate;
+  return 0;
+}
+libpthread_hidden_def(pthread_attr_getdetachstate)
+
+int pthread_attr_setschedparam(pthread_attr_t *attr,
+                               const struct sched_param *param)
+{
+  int max_prio = __sched_get_priority_max(attr->__schedpolicy);
+  int min_prio = __sched_get_priority_min(attr->__schedpolicy);
+
+  if (param->sched_priority < min_prio || param->sched_priority > max_prio)
+    return EINVAL;
+  memcpy (&attr->__schedparam, param, sizeof (struct sched_param));
+  return 0;
+}
+libpthread_hidden_def(pthread_attr_setschedparam)
+
+int pthread_attr_getschedparam(const pthread_attr_t *attr,
+                               struct sched_param *param)
+{
+  memcpy (param, &attr->__schedparam, sizeof (struct sched_param));
+  return 0;
+}
+libpthread_hidden_def(pthread_attr_getschedparam)
+
+int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
+{
+  if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR)
+    return EINVAL;
+  attr->__schedpolicy = policy;
+  return 0;
+}
+libpthread_hidden_def(pthread_attr_setschedpolicy)
+
+int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
+{
+  *policy = attr->__schedpolicy;
+  return 0;
+}
+libpthread_hidden_def(pthread_attr_getschedpolicy)
+
+int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
+{
+  if (inherit != PTHREAD_INHERIT_SCHED && inherit != PTHREAD_EXPLICIT_SCHED)
+    return EINVAL;
+  attr->__inheritsched = inherit;
+  return 0;
+}
+libpthread_hidden_def(pthread_attr_setinheritsched)
+
+int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit)
+{
+  *inherit = attr->__inheritsched;
+  return 0;
+}
+libpthread_hidden_def(pthread_attr_getinheritsched)
+
+int pthread_attr_setscope(pthread_attr_t *attr, int scope)
+{
+  switch (scope) {
+  case PTHREAD_SCOPE_SYSTEM:
+    attr->__scope = scope;
+    return 0;
+  case PTHREAD_SCOPE_PROCESS:
+    return ENOTSUP;
+  default:
+    return EINVAL;
+  }
+}
+libpthread_hidden_def(pthread_attr_setscope)
+
+int pthread_attr_getscope(const pthread_attr_t *attr, int *scope)
+{
+  *scope = attr->__scope;
+  return 0;
+}
+libpthread_hidden_def(pthread_attr_getscope)
+
+int __pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
+{
+  size_t ps = getpagesize ();
+
+  /* First round up the guard size.  */
+  guardsize = roundup (guardsize, ps);
+
+  /* The guard size must not be larger than the stack itself */
+  if (guardsize >= attr->__stacksize) return EINVAL;
+
+  attr->__guardsize = guardsize;
+
+  return 0;
+}
+weak_alias (__pthread_attr_setguardsize, pthread_attr_setguardsize)
+
+int __pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
+{
+  *guardsize = attr->__guardsize;
+  return 0;
+}
+weak_alias (__pthread_attr_getguardsize, pthread_attr_getguardsize)
+
+#if 0 /* uClibc: deprecated stuff disabled */
+int __pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
+{
+  attr->__stackaddr = stackaddr;
+  attr->__stackaddr_set = 1;
+  return 0;
+}
+weak_alias (__pthread_attr_setstackaddr, pthread_attr_setstackaddr)
+
+int __pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
+{
+  /* XXX This function has a stupid definition.  The standard specifies
+     no error value but what is if no stack address was set?  We simply
+     return the value we have in the member.  */
+  *stackaddr = attr->__stackaddr;
+  return 0;
+}
+weak_alias (__pthread_attr_getstackaddr, pthread_attr_getstackaddr)
+#endif
+
+int __pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
+{
+  /* We don't accept value smaller than PTHREAD_STACK_MIN.  */
+  if (stacksize < PTHREAD_STACK_MIN)
+    return EINVAL;
+
+  attr->__stacksize = stacksize;
+  return 0;
+}
+weak_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize)
+
+int __pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
+{
+  *stacksize = attr->__stacksize;
+  return 0;
+}
+weak_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize)

+ 219 - 0
libpthread/linuxthreads.old/cancel.c

@@ -0,0 +1,219 @@
+/* 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.                 */
+
+/* Thread cancellation */
+
+#include <errno.h>
+#include "pthread.h"
+#include "internals.h"
+#include "spinlock.h"
+#include "restart.h"
+#ifdef __UCLIBC_HAS_RPC__
+#include <rpc/rpc.h>
+extern void __rpc_thread_destroy(void);
+#endif
+#include <bits/stackinfo.h>
+
+#include <stdio.h>
+
+#ifdef _STACK_GROWS_DOWN
+# define FRAME_LEFT(frame, other) ((char *) frame >= (char *) other)
+#elif defined _STACK_GROWS_UP
+# define FRAME_LEFT(frame, other) ((char *) frame <= (char *) other)
+#else
+# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
+#endif
+
+libpthread_hidden_proto(pthread_setcancelstate)
+libpthread_hidden_proto(pthread_setcanceltype)
+
+int pthread_setcancelstate(int state, int * oldstate)
+{
+  pthread_descr self = thread_self();
+  if (state < PTHREAD_CANCEL_ENABLE || state > PTHREAD_CANCEL_DISABLE)
+    return EINVAL;
+  if (oldstate != NULL) *oldstate = THREAD_GETMEM(self, p_cancelstate);
+  THREAD_SETMEM(self, p_cancelstate, state);
+  if (THREAD_GETMEM(self, p_canceled) &&
+      THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE &&
+      THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+  return 0;
+}
+libpthread_hidden_def(pthread_setcancelstate)
+
+int pthread_setcanceltype(int type, int * oldtype)
+{
+  pthread_descr self = thread_self();
+  if (type < PTHREAD_CANCEL_DEFERRED || type > PTHREAD_CANCEL_ASYNCHRONOUS)
+    return EINVAL;
+  if (oldtype != NULL) *oldtype = THREAD_GETMEM(self, p_canceltype);
+  THREAD_SETMEM(self, p_canceltype, type);
+  if (THREAD_GETMEM(self, p_canceled) &&
+      THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE &&
+      THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+  return 0;
+}
+libpthread_hidden_def(pthread_setcanceltype)
+
+int pthread_cancel(pthread_t thread)
+{
+  pthread_handle handle = thread_handle(thread);
+  int pid;
+  int dorestart = 0;
+  pthread_descr th;
+  pthread_extricate_if *pextricate;
+  int already_canceled;
+
+  __pthread_lock(&handle->h_lock, NULL);
+  if (invalid_handle(handle, thread)) {
+    __pthread_unlock(&handle->h_lock);
+    return ESRCH;
+  }
+
+  th = handle->h_descr;
+
+  already_canceled = th->p_canceled;
+  th->p_canceled = 1;
+
+  if (th->p_cancelstate == PTHREAD_CANCEL_DISABLE || already_canceled) {
+    __pthread_unlock(&handle->h_lock);
+    return 0;
+  }
+
+  pextricate = th->p_extricate;
+  pid = th->p_pid;
+
+  /* If the thread has registered an extrication interface, then
+     invoke the interface. If it returns 1, then we succeeded in
+     dequeuing the thread from whatever waiting object it was enqueued
+     with. In that case, it is our responsibility to wake it up.
+     And also to set the p_woken_by_cancel flag so the woken thread
+     can tell that it was woken by cancellation. */
+
+  if (pextricate != NULL) {
+    dorestart = pextricate->pu_extricate_func(pextricate->pu_object, th);
+    th->p_woken_by_cancel = dorestart;
+  }
+
+  __pthread_unlock(&handle->h_lock);
+
+  /* If the thread has suspended or is about to, then we unblock it by
+     issuing a restart, instead of a cancel signal. Otherwise we send
+     the cancel signal to unblock the thread from a cancellation point,
+     or to initiate asynchronous cancellation. The restart is needed so
+     we have proper accounting of restarts; suspend decrements the thread's
+     resume count, and restart() increments it.  This also means that suspend's
+     handling of the cancel signal is obsolete. */
+
+  if (dorestart)
+    restart(th);
+  else
+    kill(pid, __pthread_sig_cancel);
+
+  return 0;
+}
+
+void pthread_testcancel(void)
+{
+  pthread_descr self = thread_self();
+  if (THREAD_GETMEM(self, p_canceled)
+      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+}
+
+void _pthread_cleanup_push(struct _pthread_cleanup_buffer * buffer,
+			   void (*routine)(void *), void * arg)
+{
+  pthread_descr self = thread_self();
+  buffer->__routine = routine;
+  buffer->__arg = arg;
+  buffer->__prev = THREAD_GETMEM(self, p_cleanup);
+  if (buffer->__prev != NULL && FRAME_LEFT (buffer, buffer->__prev))
+    buffer->__prev = NULL;
+  THREAD_SETMEM(self, p_cleanup, buffer);
+}
+
+void _pthread_cleanup_pop(struct _pthread_cleanup_buffer * buffer,
+			  int execute)
+{
+  pthread_descr self = thread_self();
+  if (execute) buffer->__routine(buffer->__arg);
+  THREAD_SETMEM(self, p_cleanup, buffer->__prev);
+}
+
+void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer * buffer,
+				 void (*routine)(void *), void * arg)
+{
+  pthread_descr self = thread_self();
+  buffer->__routine = routine;
+  buffer->__arg = arg;
+  buffer->__canceltype = THREAD_GETMEM(self, p_canceltype);
+  buffer->__prev = THREAD_GETMEM(self, p_cleanup);
+  if (buffer->__prev != NULL && FRAME_LEFT (buffer, buffer->__prev))
+    buffer->__prev = NULL;
+  THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_DEFERRED);
+  THREAD_SETMEM(self, p_cleanup, buffer);
+}
+strong_alias(_pthread_cleanup_push_defer,__pthread_cleanup_push_defer)
+
+void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer * buffer,
+				  int execute)
+{
+  pthread_descr self = thread_self();
+  if (execute) buffer->__routine(buffer->__arg);
+  THREAD_SETMEM(self, p_cleanup, buffer->__prev);
+  THREAD_SETMEM(self, p_canceltype, buffer->__canceltype);
+  if (THREAD_GETMEM(self, p_canceled) &&
+      THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE &&
+      THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+}
+strong_alias(_pthread_cleanup_pop_restore,__pthread_cleanup_pop_restore)
+
+
+void __pthread_perform_cleanup(char *currentframe)
+{
+  pthread_descr self = thread_self();
+  struct _pthread_cleanup_buffer * c;
+
+  for (c = THREAD_GETMEM(self, p_cleanup); c != NULL; c = c->__prev)
+    {
+#ifdef _STACK_GROWS_DOWN
+      if ((char *) c <= currentframe)
+	break;
+#elif defined _STACK_GROWS_UP
+      if ((char *) c >= currentframe)
+	break;
+#else
+# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
+#endif
+      c->__routine(c->__arg);
+    }
+
+#ifdef __UCLIBC_HAS_RPC__
+  /* And the TSD which needs special help.  */
+  if (THREAD_GETMEM(self, p_libc_specific[_LIBC_TSD_KEY_RPC_VARS]) != NULL)
+      __rpc_thread_destroy ();
+#endif
+}
+
+#ifndef __PIC__
+/* We need a hook to force the cancellation wrappers to be linked in when
+   static libpthread is used.  */
+extern const char __pthread_provide_wrappers;
+static const char *const __pthread_require_wrappers =
+  &__pthread_provide_wrappers;
+#endif

+ 304 - 0
libpthread/linuxthreads.old/condvar.c

@@ -0,0 +1,304 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
+/* and Pavel Krauz (krauz@fsid.cvut.cz).                                */
+/*                                                                      */
+/* 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.                 */
+
+/* Condition variables */
+
+#include <errno.h>
+#include <sched.h>
+#include <stddef.h>
+#include <sys/time.h>
+#include "pthread.h"
+#include "internals.h"
+#include "spinlock.h"
+#include "queue.h"
+#include "restart.h"
+
+int pthread_cond_init(pthread_cond_t *cond,
+                      const pthread_condattr_t *cond_attr attribute_unused)
+{
+  __pthread_init_lock(&cond->__c_lock);
+  cond->__c_waiting = NULL;
+  return 0;
+}
+libpthread_hidden_def(pthread_cond_init)
+
+int pthread_cond_destroy(pthread_cond_t *cond)
+{
+  if (cond->__c_waiting != NULL) return EBUSY;
+  return 0;
+}
+libpthread_hidden_def(pthread_cond_destroy)
+
+/* Function called by pthread_cancel to remove the thread from
+   waiting on a condition variable queue. */
+
+static int cond_extricate_func(void *obj, pthread_descr th)
+{
+  volatile pthread_descr self = thread_self();
+  pthread_cond_t *cond = obj;
+  int did_remove = 0;
+
+  __pthread_lock(&cond->__c_lock, self);
+  did_remove = remove_from_queue(&cond->__c_waiting, th);
+  __pthread_unlock(&cond->__c_lock);
+
+  return did_remove;
+}
+
+int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
+{
+  volatile pthread_descr self = thread_self();
+  pthread_extricate_if extr;
+  int already_canceled = 0;
+  int spurious_wakeup_count;
+
+  /* Check whether the mutex is locked and owned by this thread.  */
+  if (mutex->__m_kind != PTHREAD_MUTEX_TIMED_NP
+      && mutex->__m_kind != PTHREAD_MUTEX_ADAPTIVE_NP
+      && mutex->__m_owner != self)
+    return EINVAL;
+
+  /* Set up extrication interface */
+  extr.pu_object = cond;
+  extr.pu_extricate_func = cond_extricate_func;
+
+  /* Register extrication interface */
+  THREAD_SETMEM(self, p_condvar_avail, 0);
+  __pthread_set_own_extricate_if(self, &extr);
+
+  /* Atomically enqueue thread for waiting, but only if it is not
+     canceled. If the thread is canceled, then it will fall through the
+     suspend call below, and then call pthread_exit without
+     having to worry about whether it is still on the condition variable queue.
+     This depends on pthread_cancel setting p_canceled before calling the
+     extricate function. */
+
+  __pthread_lock(&cond->__c_lock, self);
+  if (!(THREAD_GETMEM(self, p_canceled)
+      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE))
+    enqueue(&cond->__c_waiting, self);
+  else
+    already_canceled = 1;
+  __pthread_unlock(&cond->__c_lock);
+
+  if (already_canceled) {
+    __pthread_set_own_extricate_if(self, 0);
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+  }
+
+  __pthread_mutex_unlock(mutex);
+
+  spurious_wakeup_count = 0;
+  while (1)
+    {
+      suspend(self);
+      if (THREAD_GETMEM(self, p_condvar_avail) == 0
+	  && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
+	      || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
+	{
+	  /* Count resumes that don't belong to us. */
+	  spurious_wakeup_count++;
+	  continue;
+	}
+      break;
+    }
+
+  __pthread_set_own_extricate_if(self, 0);
+
+  /* Check for cancellation again, to provide correct cancellation
+     point behavior */
+
+  if (THREAD_GETMEM(self, p_woken_by_cancel)
+      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
+    THREAD_SETMEM(self, p_woken_by_cancel, 0);
+    __pthread_mutex_lock(mutex);
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+  }
+
+  /* Put back any resumes we caught that don't belong to us. */
+  while (spurious_wakeup_count--)
+    restart(self);
+
+  __pthread_mutex_lock(mutex);
+  return 0;
+}
+libpthread_hidden_def(pthread_cond_wait)
+
+static int
+pthread_cond_timedwait_relative(pthread_cond_t *cond,
+				pthread_mutex_t *mutex,
+				const struct timespec * abstime)
+{
+  volatile pthread_descr self = thread_self();
+  int already_canceled = 0;
+  pthread_extricate_if extr;
+  int spurious_wakeup_count;
+
+  /* Check whether the mutex is locked and owned by this thread.  */
+  if (mutex->__m_kind != PTHREAD_MUTEX_TIMED_NP
+      && mutex->__m_kind != PTHREAD_MUTEX_ADAPTIVE_NP
+      && mutex->__m_owner != self)
+    return EINVAL;
+
+  /* Set up extrication interface */
+  extr.pu_object = cond;
+  extr.pu_extricate_func = cond_extricate_func;
+
+  /* Register extrication interface */
+  THREAD_SETMEM(self, p_condvar_avail, 0);
+  __pthread_set_own_extricate_if(self, &extr);
+
+  /* Enqueue to wait on the condition and check for cancellation. */
+  __pthread_lock(&cond->__c_lock, self);
+  if (!(THREAD_GETMEM(self, p_canceled)
+      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE))
+    enqueue(&cond->__c_waiting, self);
+  else
+    already_canceled = 1;
+  __pthread_unlock(&cond->__c_lock);
+
+  if (already_canceled) {
+    __pthread_set_own_extricate_if(self, 0);
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+  }
+
+  __pthread_mutex_unlock(mutex);
+
+  spurious_wakeup_count = 0;
+  while (1)
+    {
+      if (!timedsuspend(self, abstime)) {
+	int was_on_queue;
+
+	/* __pthread_lock will queue back any spurious restarts that
+	   may happen to it. */
+
+	__pthread_lock(&cond->__c_lock, self);
+	was_on_queue = remove_from_queue(&cond->__c_waiting, self);
+	__pthread_unlock(&cond->__c_lock);
+
+	if (was_on_queue) {
+	  __pthread_set_own_extricate_if(self, 0);
+	  __pthread_mutex_lock(mutex);
+	  return ETIMEDOUT;
+	}
+
+	/* Eat the outstanding restart() from the signaller */
+	suspend(self);
+      }
+
+      if (THREAD_GETMEM(self, p_condvar_avail) == 0
+	  && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
+	      || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
+	{
+	  /* Count resumes that don't belong to us. */
+	  spurious_wakeup_count++;
+	  continue;
+	}
+      break;
+    }
+
+  __pthread_set_own_extricate_if(self, 0);
+
+  /* The remaining logic is the same as in other cancellable waits,
+     such as pthread_join sem_wait or pthread_cond wait. */
+
+  if (THREAD_GETMEM(self, p_woken_by_cancel)
+      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
+    THREAD_SETMEM(self, p_woken_by_cancel, 0);
+    __pthread_mutex_lock(mutex);
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+  }
+
+  /* Put back any resumes we caught that don't belong to us. */
+  while (spurious_wakeup_count--)
+    restart(self);
+
+  __pthread_mutex_lock(mutex);
+  return 0;
+}
+
+int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
+                           const struct timespec * abstime)
+{
+  /* Indirect call through pointer! */
+  return pthread_cond_timedwait_relative(cond, mutex, abstime);
+}
+libpthread_hidden_def(pthread_cond_timedwait)
+
+int pthread_cond_signal(pthread_cond_t *cond)
+{
+  pthread_descr th;
+
+  __pthread_lock(&cond->__c_lock, NULL);
+  th = dequeue(&cond->__c_waiting);
+  __pthread_unlock(&cond->__c_lock);
+  if (th != NULL) {
+    th->p_condvar_avail = 1;
+    WRITE_MEMORY_BARRIER();
+    restart(th);
+  }
+  return 0;
+}
+libpthread_hidden_def(pthread_cond_signal)
+
+int pthread_cond_broadcast(pthread_cond_t *cond)
+{
+  pthread_descr tosignal, th;
+
+  __pthread_lock(&cond->__c_lock, NULL);
+  /* Copy the current state of the waiting queue and empty it */
+  tosignal = cond->__c_waiting;
+  cond->__c_waiting = NULL;
+  __pthread_unlock(&cond->__c_lock);
+  /* Now signal each process in the queue */
+  while ((th = dequeue(&tosignal)) != NULL) {
+    th->p_condvar_avail = 1;
+    WRITE_MEMORY_BARRIER();
+    restart(th);
+  }
+  return 0;
+}
+libpthread_hidden_def(pthread_cond_broadcast)
+
+int pthread_condattr_init(pthread_condattr_t *attr attribute_unused)
+{
+  return 0;
+}
+libpthread_hidden_def(pthread_condattr_init)
+
+int pthread_condattr_destroy(pthread_condattr_t *attr attribute_unused)
+{
+  return 0;
+}
+libpthread_hidden_def(pthread_condattr_destroy)
+
+int pthread_condattr_getpshared (const pthread_condattr_t *attr attribute_unused, int *pshared)
+{
+  *pshared = PTHREAD_PROCESS_PRIVATE;
+  return 0;
+}
+
+int pthread_condattr_setpshared (pthread_condattr_t *attr attribute_unused, int pshared)
+{
+  if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
+    return EINVAL;
+
+  /* For now it is not possible to shared a conditional variable.  */
+  if (pshared != PTHREAD_PROCESS_PRIVATE)
+    return ENOSYS;
+
+  return 0;
+}

+ 0 - 0
libpthread/linuxthreads/debug.h → libpthread/linuxthreads.old/debug.h


+ 35 - 0
libpthread/linuxthreads.old/errno.c

@@ -0,0 +1,35 @@
+/* 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.                 */
+
+/* Define the location of errno for the remainder of the C library */
+
+#include <errno.h>
+#include <netdb.h>
+#include "pthread.h"
+#include "internals.h"
+#include <stdio.h>
+
+int *
+__errno_location (void)
+{
+  pthread_descr self = thread_self();
+  return THREAD_GETMEM (self, p_errnop);
+}
+
+int *
+__h_errno_location (void)
+{
+  pthread_descr self = thread_self();
+  return THREAD_GETMEM (self, p_h_errnop);
+}

+ 36 - 0
libpthread/linuxthreads.old/events.c

@@ -0,0 +1,36 @@
+/* Event functions used while debugging.
+   Copyright (C) 1999 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   see <http://www.gnu.org/licenses/>.  */
+
+/* The functions contained here do nothing, they just return.  */
+
+#include "internals.h"
+
+void
+__linuxthreads_create_event (void)
+{
+}
+
+void
+__linuxthreads_death_event (void)
+{
+}
+
+void
+__linuxthreads_reap_event (void)
+{
+}

+ 173 - 0
libpthread/linuxthreads.old/forward.c

@@ -0,0 +1,173 @@
+/* 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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <features.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+
+/* psm: keep this before internals.h */
+#if 0
+vda: here is why:
+headers contain libc_hidden_proto(foo).
+In libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-lock.h
+adding libc_hidden_proto(foo) just before weak_extern (__pthread_initialize)
+will not warn:
+    /* libc_hidden_proto(foo) */
+    weak_extern (__pthread_initialize)
+    /* libc_hidden_proto(foo) */
+but adding after will! Which is extremely strange -
+weak_extern expands into just "#pragma weak __pthread_initialize".
+TODO: determine whether it is a gcc bug or what
+(see gcc.gnu.org/PR36282).
+For now, just include all headers before internals.h
+(they are again included in internals.h - maybe remove them there later)
+#endif
+
+#include <string.h>
+#include <limits.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+
+#include "internals.h"
+
+/* Pointers to the libc functions.  */
+struct pthread_functions __libc_pthread_functions attribute_hidden;
+
+
+# define FORWARD2(name, rettype, decl, params, defaction) \
+rettype									      \
+name decl								      \
+{									      \
+  if (__libc_pthread_functions.ptr_##name == NULL)			      \
+    defaction;								      \
+									      \
+  return __libc_pthread_functions.ptr_##name params;			      \
+}
+
+# define FORWARD(name, decl, params, defretval) \
+  FORWARD2 (name, int, decl, params, return defretval)
+
+FORWARD (pthread_attr_destroy, (pthread_attr_t *attr), (attr), 0)
+
+FORWARD (pthread_attr_init, (pthread_attr_t *attr), (attr), 0)
+
+FORWARD (pthread_attr_getdetachstate,
+	 (const pthread_attr_t *attr, int *detachstate), (attr, detachstate),
+	 0)
+FORWARD (pthread_attr_setdetachstate, (pthread_attr_t *attr, int detachstate),
+	 (attr, detachstate), 0)
+
+FORWARD (pthread_attr_getinheritsched,
+	 (const pthread_attr_t *attr, int *inherit), (attr, inherit), 0)
+FORWARD (pthread_attr_setinheritsched, (pthread_attr_t *attr, int inherit),
+	 (attr, inherit), 0)
+
+FORWARD (pthread_attr_getschedparam,
+	 (const pthread_attr_t *attr, struct sched_param *param),
+	 (attr, param), 0)
+FORWARD (pthread_attr_setschedparam,
+	 (pthread_attr_t *attr, const struct sched_param *param),
+	 (attr, param), 0)
+
+FORWARD (pthread_attr_getschedpolicy,
+	 (const pthread_attr_t *attr, int *policy), (attr, policy), 0)
+FORWARD (pthread_attr_setschedpolicy, (pthread_attr_t *attr, int policy),
+	 (attr, policy), 0)
+
+FORWARD (pthread_attr_getscope,
+	 (const pthread_attr_t *attr, int *scope), (attr, scope), 0)
+FORWARD (pthread_attr_setscope, (pthread_attr_t *attr, int scope),
+	 (attr, scope), 0)
+
+
+FORWARD (pthread_condattr_destroy, (pthread_condattr_t *attr), (attr), 0)
+FORWARD (pthread_condattr_init, (pthread_condattr_t *attr), (attr), 0)
+
+
+FORWARD (pthread_cond_broadcast, (pthread_cond_t *cond), (cond), 0)
+
+FORWARD (pthread_cond_destroy, (pthread_cond_t *cond), (cond), 0)
+
+FORWARD (pthread_cond_init,
+	 (pthread_cond_t *cond, const pthread_condattr_t *cond_attr),
+	 (cond, cond_attr), 0)
+
+FORWARD (pthread_cond_signal, (pthread_cond_t *cond), (cond), 0)
+
+FORWARD (pthread_cond_wait, (pthread_cond_t *cond, pthread_mutex_t *mutex),
+	 (cond, mutex), 0)
+
+FORWARD (pthread_cond_timedwait,
+	 (pthread_cond_t *cond, pthread_mutex_t *mutex,
+	  const struct timespec *abstime), (cond, mutex, abstime), 0)
+
+
+FORWARD (pthread_equal, (pthread_t thread1, pthread_t thread2),
+	 (thread1, thread2), 1)
+
+
+/* Use an alias to avoid warning, as pthread_exit is declared noreturn.  */
+FORWARD2 (__pthread_exit, void, (void *retval), (retval), exit (EXIT_SUCCESS))
+strong_alias (__pthread_exit, pthread_exit)
+
+
+FORWARD (pthread_getschedparam,
+	 (pthread_t target_thread, int *policy, struct sched_param *param),
+	 (target_thread, policy, param), 0)
+FORWARD (pthread_setschedparam,
+	 (pthread_t target_thread, int policy,
+	  const struct sched_param *param), (target_thread, policy, param), 0)
+
+
+FORWARD (pthread_mutex_destroy, (pthread_mutex_t *mutex), (mutex), 0)
+
+FORWARD (pthread_mutex_init,
+	 (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr),
+	 (mutex, mutexattr), 0)
+strong_alias(pthread_mutex_init, __pthread_mutex_init)
+
+FORWARD (pthread_mutex_lock, (pthread_mutex_t *mutex), (mutex), 0)
+strong_alias(pthread_mutex_lock, __pthread_mutex_lock)
+
+FORWARD (pthread_mutex_trylock, (pthread_mutex_t *mutex), (mutex), 0)
+strong_alias(pthread_mutex_trylock, __pthread_mutex_trylock)
+
+FORWARD (pthread_mutex_unlock, (pthread_mutex_t *mutex), (mutex), 0)
+strong_alias(pthread_mutex_unlock, __pthread_mutex_unlock)
+
+FORWARD2 (pthread_self, pthread_t, (void), (), return 0)
+
+
+FORWARD (pthread_setcancelstate, (int state, int *oldstate), (state, oldstate),
+	 0)
+
+FORWARD (pthread_setcanceltype, (int type, int *oldtype), (type, oldtype), 0)
+
+#if 0
+FORWARD2 (_pthread_cleanup_push, void, (struct _pthread_cleanup_buffer * buffer, void (*routine)(void *), void * arg), (buffer, routine, arg), return)
+#endif
+FORWARD2 (_pthread_cleanup_push_defer, void, (struct _pthread_cleanup_buffer * buffer, void (*routine)(void *), void * arg), (buffer, routine, arg), return)
+
+#if 0
+FORWARD2 (_pthread_cleanup_pop, void, (struct _pthread_cleanup_buffer * buffer, int execute), (buffer, execute), return)
+#endif
+FORWARD2 (_pthread_cleanup_pop_restore, void, (struct _pthread_cleanup_buffer * buffer, int execute), (buffer, execute), return)

+ 529 - 0
libpthread/linuxthreads.old/internals.h

@@ -0,0 +1,529 @@
+/* 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.                 */
+
+#ifndef _INTERNALS_H
+#define _INTERNALS_H   1
+
+/* Internal data structures */
+
+/* Includes */
+
+#include <bits/libc-tsd.h> /* for _LIBC_TSD_KEY_N */
+#include <limits.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <unistd.h>
+#include <bits/stackinfo.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include "pt-machine.h"
+#include "semaphore.h"
+#include "../linuxthreads.old_db/thread_dbP.h"
+#ifdef __UCLIBC_HAS_XLOCALE__
+#include <bits/uClibc_locale.h>
+#endif /* __UCLIBC_HAS_XLOCALE__ */
+
+/* Use a funky version in a probably vein attempt at preventing gdb
+ * from dlopen()'ing glibc's libthread_db library... */
+#define VERSION __stringify(__UCLIBC_MAJOR__) "." __stringify(__UCLIBC_MINOR__) "." __stringify(__UCLIBC_SUBLEVEL__)
+
+#ifndef THREAD_GETMEM
+# define THREAD_GETMEM(descr, member) descr->member
+#endif
+#ifndef THREAD_GETMEM_NC
+# define THREAD_GETMEM_NC(descr, member) descr->member
+#endif
+#ifndef THREAD_SETMEM
+# define THREAD_SETMEM(descr, member, value) descr->member = (value)
+#endif
+#ifndef THREAD_SETMEM_NC
+# define THREAD_SETMEM_NC(descr, member, value) descr->member = (value)
+#endif
+
+/* Arguments passed to thread creation routine */
+
+struct pthread_start_args {
+  void * (*start_routine)(void *); /* function to run */
+  void * arg;                   /* its argument */
+  sigset_t mask;                /* initial signal mask for thread */
+  int schedpolicy;              /* initial scheduling policy (if any) */
+  struct sched_param schedparam; /* initial scheduling parameters (if any) */
+};
+
+
+/* We keep thread specific data in a special data structure, a two-level
+   array.  The top-level array contains pointers to dynamically allocated
+   arrays of a certain number of data pointers.  So we can implement a
+   sparse array.  Each dynamic second-level array has
+	PTHREAD_KEY_2NDLEVEL_SIZE
+   entries.  This value shouldn't be too large.  */
+#define PTHREAD_KEY_2NDLEVEL_SIZE	32
+
+/* We need to address PTHREAD_KEYS_MAX key with PTHREAD_KEY_2NDLEVEL_SIZE
+   keys in each subarray.  */
+#define PTHREAD_KEY_1STLEVEL_SIZE \
+  ((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1) \
+   / PTHREAD_KEY_2NDLEVEL_SIZE)
+
+typedef void (*destr_function)(void *);
+
+struct pthread_key_struct {
+  int in_use;                   /* already allocated? */
+  destr_function destr;         /* destruction routine */
+};
+
+
+#define PTHREAD_START_ARGS_INITIALIZER { NULL, NULL, {{0, }}, 0, { 0 } }
+
+/* The type of thread descriptors */
+
+typedef struct _pthread_descr_struct * pthread_descr;
+
+/* Callback interface for removing the thread from waiting on an
+   object if it is cancelled while waiting or about to wait.
+   This hold a pointer to the object, and a pointer to a function
+   which ``extricates'' the thread from its enqueued state.
+   The function takes two arguments: pointer to the wait object,
+   and a pointer to the thread. It returns 1 if an extrication
+   actually occured, and hence the thread must also be signalled.
+   It returns 0 if the thread had already been extricated. */
+
+typedef struct _pthread_extricate_struct {
+    void *pu_object;
+    int (*pu_extricate_func)(void *, pthread_descr);
+} pthread_extricate_if;
+
+/* Atomic counter made possible by compare_and_swap */
+
+struct pthread_atomic {
+  long p_count;
+  int p_spinlock;
+};
+
+/* Context info for read write locks. The pthread_rwlock_info structure
+   is information about a lock that has been read-locked by the thread
+   in whose list this structure appears. The pthread_rwlock_context
+   is embedded in the thread context and contains a pointer to the
+   head of the list of lock info structures, as well as a count of
+   read locks that are untracked, because no info structure could be
+   allocated for them. */
+
+struct _pthread_rwlock_t;
+
+typedef struct _pthread_rwlock_info {
+  struct _pthread_rwlock_info *pr_next;
+  struct _pthread_rwlock_t *pr_lock;
+  int pr_lock_count;
+} pthread_readlock_info;
+
+struct _pthread_descr_struct {
+  pthread_descr p_nextlive, p_prevlive;
+                                /* Double chaining of active threads */
+  pthread_descr p_nextwaiting;  /* Next element in the queue holding the thr */
+  pthread_descr p_nextlock;	/* can be on a queue and waiting on a lock */
+  pthread_t p_tid;              /* Thread identifier */
+  int p_pid;                    /* PID of Unix process */
+  int p_priority;               /* Thread priority (== 0 if not realtime) */
+  struct _pthread_fastlock * p_lock; /* Spinlock for synchronized accesses */
+  int p_signal;                 /* last signal received */
+  sigjmp_buf * p_signal_jmp;    /* where to siglongjmp on a signal or NULL */
+  sigjmp_buf * p_cancel_jmp;    /* where to siglongjmp on a cancel or NULL */
+  char p_terminated;            /* true if terminated e.g. by pthread_exit */
+  char p_detached;              /* true if detached */
+  char p_exited;                /* true if the assoc. process terminated */
+  void * p_retval;              /* placeholder for return value */
+  int p_retcode;                /* placeholder for return code */
+  pthread_descr p_joining;      /* thread joining on that thread or NULL */
+  struct _pthread_cleanup_buffer * p_cleanup; /* cleanup functions */
+  char p_cancelstate;           /* cancellation state */
+  char p_canceltype;            /* cancellation type (deferred/async) */
+  char p_canceled;              /* cancellation request pending */
+  int * p_errnop;               /* pointer to used errno variable */
+  int p_errno;                  /* error returned by last system call */
+  int * p_h_errnop;             /* pointer to used h_errno variable */
+  int p_h_errno;                /* error returned by last netdb function */
+  char * p_in_sighandler;       /* stack address of sighandler, or NULL */
+  char p_sigwaiting;            /* true if a sigwait() is in progress */
+  struct pthread_start_args p_start_args; /* arguments for thread creation */
+  void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE]; /* thread-specific data */
+  void * p_libc_specific[_LIBC_TSD_KEY_N]; /* thread-specific data for libc */
+  int p_userstack;		/* nonzero if the user provided the stack */
+  void *p_guardaddr;		/* address of guard area or NULL */
+  size_t p_guardsize;		/* size of guard area */
+  pthread_descr p_self;		/* Pointer to this structure */
+  int p_nr;                     /* Index of descriptor in __pthread_handles */
+  int p_report_events;         /* Nonzero if events must be reported.  */
+  td_eventbuf_t p_eventbuf;     /* Data for event.  */
+  struct pthread_atomic p_resume_count; /* number of times restart() was
+					   called on thread */
+  char p_woken_by_cancel;       /* cancellation performed wakeup */
+  char p_condvar_avail;         /* flag if conditional variable became avail */
+  char p_sem_avail;             /* flag if semaphore became available */
+  pthread_extricate_if *p_extricate; /* See above */
+  pthread_readlock_info *p_readlock_list;  /* List of readlock info structs */
+  pthread_readlock_info *p_readlock_free;  /* Free list of structs */
+  int p_untracked_readlock_count;	/* Readlocks not tracked by list */
+  /* New elements must be added at the end.  */
+#ifdef __UCLIBC_HAS_XLOCALE__
+  __locale_t locale; /* thread-specific locale from uselocale() only! */
+#endif /* __UCLIBC_HAS_XLOCALE__ */
+} __attribute__ ((aligned(32))); /* We need to align the structure so that
+				    doubles are aligned properly.  This is 8
+				    bytes on MIPS and 16 bytes on MIPS64.
+				    32 bytes might give better cache
+				    utilization.  */
+
+/* The type of thread handles. */
+
+typedef struct pthread_handle_struct * pthread_handle;
+
+struct pthread_handle_struct {
+  struct _pthread_fastlock h_lock; /* Fast lock for sychronized access */
+  pthread_descr h_descr;        /* Thread descriptor or NULL if invalid */
+  char * h_bottom;              /* Lowest address in the stack thread */
+};
+
+/* The type of messages sent to the thread manager thread */
+
+struct pthread_request {
+  pthread_descr req_thread;     /* Thread doing the request */
+  enum {                        /* Request kind */
+    REQ_CREATE, REQ_FREE, REQ_PROCESS_EXIT, REQ_MAIN_THREAD_EXIT,
+    REQ_POST, REQ_DEBUG, REQ_KICK
+  } req_kind;
+  union {                       /* Arguments for request */
+    struct {                    /* For REQ_CREATE: */
+      const pthread_attr_t * attr; /* thread attributes */
+      void * (*fn)(void *);     /*   start function */
+      void * arg;               /*   argument to start function */
+      sigset_t mask;            /*   signal mask */
+    } create;
+    struct {                    /* For REQ_FREE: */
+      pthread_t thread_id;      /*   identifier of thread to free */
+    } free;
+    struct {                    /* For REQ_PROCESS_EXIT: */
+      int code;                 /*   exit status */
+    } exit;
+    void * post;                /* For REQ_POST: the semaphore */
+  } req_args;
+};
+
+
+/* Signals used for suspend/restart and for cancellation notification.  */
+
+extern int __pthread_sig_restart;
+extern int __pthread_sig_cancel;
+
+/* Signal used for interfacing with gdb */
+
+extern int __pthread_sig_debug;
+
+/* Global array of thread handles, used for validating a thread id
+   and retrieving the corresponding thread descriptor. Also used for
+   mapping the available stack segments. */
+
+extern struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX];
+
+/* Descriptor of the initial thread */
+
+extern struct _pthread_descr_struct __pthread_initial_thread;
+
+/* Descriptor of the manager thread */
+
+extern struct _pthread_descr_struct __pthread_manager_thread;
+
+/* Descriptor of the main thread */
+
+extern pthread_descr __pthread_main_thread;
+
+/* Limit between the stack of the initial thread (above) and the
+   stacks of other threads (below). Aligned on a STACK_SIZE boundary.
+   Initially 0, meaning that the current thread is (by definition)
+   the initial thread. */
+
+extern char *__pthread_initial_thread_bos;
+#ifndef __ARCH_USE_MMU__
+/* For non-MMU systems, we have no idea the bounds of the initial thread
+ * stack, so we have to track it on the fly relative to other stacks.  Do
+ * so by scaling back our assumptions on the limits of the bos/tos relative
+ * to the known mid point.  See also the comments in pthread_initialize(). */
+extern char *__pthread_initial_thread_tos, *__pthread_initial_thread_mid;
+#define NOMMU_INITIAL_THREAD_BOUNDS(tos,bos) \
+	do { \
+		char *__tos = (tos); \
+		char *__bos = (bos); \
+		if (__tos >= __pthread_initial_thread_bos && \
+		    __bos < __pthread_initial_thread_tos) { \
+			if (__bos < __pthread_initial_thread_mid) \
+				__pthread_initial_thread_bos = __tos; \
+			else \
+				__pthread_initial_thread_tos = __bos; \
+		} \
+	} while (0)
+#else
+#define NOMMU_INITIAL_THREAD_BOUNDS(tos,bos) /* empty */
+#endif /* __ARCH_USE_MMU__ */
+
+
+/* Indicate whether at least one thread has a user-defined stack (if 1),
+   or all threads have stacks supplied by LinuxThreads (if 0). */
+
+extern int __pthread_nonstandard_stacks;
+
+/* File descriptor for sending requests to the thread manager.
+   Initially -1, meaning that __pthread_initialize_manager must be called. */
+
+extern int __pthread_manager_request;
+
+/* Other end of the pipe for sending requests to the thread manager. */
+
+extern int __pthread_manager_reader;
+
+/* Limits of the thread manager stack. */
+
+extern char *__pthread_manager_thread_bos;
+extern char *__pthread_manager_thread_tos;
+
+/* Pending request for a process-wide exit */
+
+extern int __pthread_exit_requested, __pthread_exit_code;
+
+/* Set to 1 by gdb if we're debugging */
+
+extern volatile int __pthread_threads_debug;
+
+/* Globally enabled events.  */
+extern volatile td_thr_events_t __pthread_threads_events;
+
+/* Pointer to descriptor of thread with last event.  */
+extern volatile pthread_descr __pthread_last_event;
+
+/* Return the handle corresponding to a thread id */
+
+static __inline__ pthread_handle thread_handle(pthread_t id)
+{
+  return &__pthread_handles[id % PTHREAD_THREADS_MAX];
+}
+
+/* Validate a thread handle. Must have acquired h->h_spinlock before. */
+
+static __inline__ int invalid_handle(pthread_handle h, pthread_t id)
+{
+  return h->h_descr == NULL || h->h_descr->p_tid != id;
+}
+
+/* Fill in defaults left unspecified by pt-machine.h.  */
+
+/* The page size we can get from the system.  This should likely not be
+   changed by the machine file but, you never know.  */
+#define __PAGE_SIZE  (sysconf (_SC_PAGESIZE))
+
+/* The max size of the thread stack segments.  If the default
+   THREAD_SELF implementation is used, this must be a power of two and
+   a multiple of __PAGE_SIZE.  */
+#ifndef STACK_SIZE
+#ifdef __ARCH_USE_MMU__
+#define STACK_SIZE  (2 * 1024 * 1024)
+#else
+#define STACK_SIZE  (4 * __PAGE_SIZE)
+#endif
+#endif
+
+/* The initial size of the thread stack.  Must be a multiple of __PAGE_SIZE.  */
+#ifndef INITIAL_STACK_SIZE
+#define INITIAL_STACK_SIZE  (4 * __PAGE_SIZE)
+#endif
+
+/* Size of the thread manager stack. The "- 32" avoids wasting space
+   with some malloc() implementations. */
+#ifndef THREAD_MANAGER_STACK_SIZE
+#define THREAD_MANAGER_STACK_SIZE  (2 * __PAGE_SIZE - 32)
+#endif
+
+/* The base of the "array" of thread stacks.  The array will grow down from
+   here.  Defaults to the calculated bottom of the initial application
+   stack.  */
+#ifndef THREAD_STACK_START_ADDRESS
+#define THREAD_STACK_START_ADDRESS  __pthread_initial_thread_bos
+#endif
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#ifndef CURRENT_STACK_FRAME
+#define CURRENT_STACK_FRAME  ({ char __csf; &__csf; })
+#endif
+
+/* If MEMORY_BARRIER isn't defined in pt-machine.h, assume the
+   architecture doesn't need a memory barrier instruction (e.g. Intel
+   x86).  Still we need the compiler to respect the barrier and emit
+   all outstanding operations which modify memory.  Some architectures
+   distinguish between full, read and write barriers.  */
+#ifndef MEMORY_BARRIER
+#define MEMORY_BARRIER() __asm__ ("" : : : "memory")
+#endif
+#ifndef READ_MEMORY_BARRIER
+#define READ_MEMORY_BARRIER() MEMORY_BARRIER()
+#endif
+#ifndef WRITE_MEMORY_BARRIER
+#define WRITE_MEMORY_BARRIER() MEMORY_BARRIER()
+#endif
+
+/* Recover thread descriptor for the current thread */
+
+extern pthread_descr __pthread_find_self (void) __attribute__ ((const)) attribute_hidden;
+
+static __inline__ pthread_descr thread_self (void) __attribute__ ((const));
+static __inline__ pthread_descr thread_self (void)
+{
+#ifdef THREAD_SELF
+  return THREAD_SELF;
+#else
+  char *sp = CURRENT_STACK_FRAME;
+#ifdef __ARCH_USE_MMU__
+  if (sp >= __pthread_initial_thread_bos)
+    return &__pthread_initial_thread;
+  else if (sp >= __pthread_manager_thread_bos
+	   && sp < __pthread_manager_thread_tos)
+    return &__pthread_manager_thread;
+  else if (__pthread_nonstandard_stacks)
+    return __pthread_find_self();
+  else
+    return (pthread_descr)(((unsigned long)sp | (STACK_SIZE-1))+1) - 1;
+#else
+  /* For non-MMU we need to be more careful about the initial thread stack.
+   * We refine the initial thread stack bounds dynamically as we allocate
+   * the other stack frame such that it doesn't overlap with them. Then
+   * we can be sure to pick the right thread according to the current SP */
+
+  /* Since we allow other stack frames to be above or below, we need to
+   * treat this case special. When pthread_initialize() wasn't called yet,
+   * only the initial thread is there. */
+  if (__pthread_initial_thread_bos == NULL) {
+      return &__pthread_initial_thread;
+  }
+  else if (sp >= __pthread_initial_thread_bos
+	   && sp < __pthread_initial_thread_tos) {
+      return &__pthread_initial_thread;
+  }
+  else if (sp >= __pthread_manager_thread_bos
+	   && sp < __pthread_manager_thread_tos) {
+      return &__pthread_manager_thread;
+  }
+  else {
+      return __pthread_find_self();
+  }
+#endif /* __ARCH_USE_MMU__ */
+#endif
+}
+
+/* Max number of times we must spin on a spinlock calling sched_yield().
+   After MAX_SPIN_COUNT iterations, we put the calling thread to sleep. */
+
+#ifndef MAX_SPIN_COUNT
+#define MAX_SPIN_COUNT 50
+#endif
+
+/* Duration of sleep (in nanoseconds) when we can't acquire a spinlock
+   after MAX_SPIN_COUNT iterations of sched_yield().
+   With the 2.0 and 2.1 kernels, this MUST BE > 2ms.
+   (Otherwise the kernel does busy-waiting for realtime threads,
+    giving other threads no chance to run.) */
+
+#ifndef SPIN_SLEEP_DURATION
+#define SPIN_SLEEP_DURATION 2000001
+#endif
+
+/* Defined and used in libc.so.  */
+extern int __libc_multiple_threads attribute_hidden;
+extern int __librt_multiple_threads;
+
+/* Internal global functions */
+
+void __pthread_do_exit (void *retval, char *currentframe)
+     __attribute__ ((__noreturn__)) attribute_hidden;
+void __pthread_destroy_specifics(void) attribute_hidden;
+void __pthread_perform_cleanup(char *currentframe) attribute_hidden;
+int __pthread_initialize_manager(void) attribute_hidden;
+void __pthread_message(char * fmt, ...)
+     __attribute__ ((__format__ (printf, 1, 2))) attribute_hidden;
+int __pthread_manager(void *reqfd) attribute_hidden;
+int __pthread_manager_event(void *reqfd) attribute_hidden;
+void __pthread_manager_sighandler(int sig) attribute_hidden;
+void __pthread_reset_main_thread(void) attribute_hidden;
+void __fresetlockfiles(void) attribute_hidden;
+void __pthread_manager_adjust_prio(int thread_prio) attribute_hidden;
+void __pthread_initialize_minimal (void);
+
+extern void __pthread_exit (void *retval)
+#if defined NOT_IN_libc && defined IS_IN_libpthread
+	attribute_noreturn
+#endif
+	;
+
+extern int __pthread_attr_setguardsize(pthread_attr_t *__attr,
+				       size_t __guardsize) attribute_hidden;
+extern int __pthread_attr_getguardsize(const pthread_attr_t *__attr,
+				       size_t *__guardsize) attribute_hidden;
+extern int __pthread_attr_setstackaddr(pthread_attr_t *__attr,
+				       void *__stackaddr) attribute_hidden;
+extern int __pthread_attr_getstackaddr(const pthread_attr_t *__attr,
+				       void **__stackaddr) attribute_hidden;
+extern int __pthread_attr_setstacksize(pthread_attr_t *__attr,
+				       size_t __stacksize) attribute_hidden;
+extern int __pthread_attr_getstacksize(const pthread_attr_t *__attr,
+				       size_t *__stacksize) attribute_hidden;
+extern int __pthread_getconcurrency(void) attribute_hidden;
+extern int __pthread_setconcurrency(int __level) attribute_hidden;
+extern void __pthread_kill_other_threads_np(void) attribute_hidden;
+
+extern void __pthread_restart_old(pthread_descr th) attribute_hidden;
+extern void __pthread_suspend_old(pthread_descr self) attribute_hidden;
+extern int __pthread_timedsuspend_old(pthread_descr self, const struct timespec *abstime) attribute_hidden;
+
+extern void __pthread_restart_new(pthread_descr th) attribute_hidden;
+extern void __pthread_suspend_new(pthread_descr self) attribute_hidden;
+extern int __pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime) attribute_hidden;
+
+extern void __pthread_wait_for_restart_signal(pthread_descr self) attribute_hidden;
+
+/* Global pointers to old or new suspend functions */
+
+extern void (*__pthread_restart)(pthread_descr) attribute_hidden;
+extern void (*__pthread_suspend)(pthread_descr) attribute_hidden;
+
+#if defined NOT_IN_libc && defined IS_IN_libpthread
+extern __typeof(pthread_mutex_init) __pthread_mutex_init attribute_hidden;
+extern __typeof(pthread_mutex_destroy) __pthread_mutex_destroy attribute_hidden;
+extern __typeof(pthread_mutex_lock) __pthread_mutex_lock attribute_hidden;
+extern __typeof(pthread_mutex_trylock) __pthread_mutex_trylock attribute_hidden;
+extern __typeof(pthread_mutex_unlock) __pthread_mutex_unlock attribute_hidden;
+#endif
+
+/* Prototypes for some of the new semaphore functions.  */
+/*extern int __new_sem_post (sem_t * sem);*/
+
+/* TSD.  */
+extern int __pthread_internal_tsd_set (int key, const void * pointer);
+extern void * __pthread_internal_tsd_get (int key);
+extern void ** __attribute__ ((__const__))
+  __pthread_internal_tsd_address (int key);
+
+/* The functions called the signal events.  */
+extern void __linuxthreads_create_event (void) attribute_hidden;
+extern void __linuxthreads_death_event (void) attribute_hidden;
+extern void __linuxthreads_reap_event (void) attribute_hidden;
+
+#include <pthread-functions.h>
+
+#endif /* internals.h */

+ 231 - 0
libpthread/linuxthreads.old/join.c

@@ -0,0 +1,231 @@
+/* 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.                 */
+
+/* Thread termination and joining */
+
+#include <features.h>
+#include <errno.h>
+#include <sched.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "pthread.h"
+#include "internals.h"
+#include "spinlock.h"
+#include "restart.h"
+#include "debug.h" /* PDEBUG, added by StS */
+
+libpthread_hidden_proto(pthread_exit)
+void pthread_exit(void * retval)
+{
+  __pthread_do_exit (retval, CURRENT_STACK_FRAME);
+}
+libpthread_hidden_def (pthread_exit)
+
+void __pthread_do_exit(void *retval, char *currentframe)
+{
+  pthread_descr self = thread_self();
+  pthread_descr joining;
+  struct pthread_request request;
+  PDEBUG("self=%p, pid=%d\n", self, self->p_pid);
+
+  /* obey POSIX behavior and prevent cancellation functions from
+   * being called more than once.
+   * http://sourceware.org/ml/libc-ports/2006-10/msg00043.html
+   */
+  THREAD_SETMEM(self, p_cancelstate, PTHREAD_CANCEL_DISABLE);
+  THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_DEFERRED);
+
+  /* Call cleanup functions and destroy the thread-specific data */
+  __pthread_perform_cleanup(currentframe);
+  __pthread_destroy_specifics();
+  /* Store return value */
+  __pthread_lock(THREAD_GETMEM(self, p_lock), self);
+  THREAD_SETMEM(self, p_retval, retval);
+  /* See whether we have to signal the death.  */
+  if (THREAD_GETMEM(self, p_report_events))
+    {
+      /* See whether TD_DEATH is in any of the mask.  */
+      int idx = __td_eventword (TD_DEATH);
+      uint32_t mask = __td_eventmask (TD_DEATH);
+
+      if ((mask & (__pthread_threads_events.event_bits[idx]
+		   | THREAD_GETMEM_NC(self,
+				   p_eventbuf.eventmask).event_bits[idx]))
+	  != 0)
+	{
+	  /* Yep, we have to signal the death.  */
+	  THREAD_SETMEM(self, p_eventbuf.eventnum, TD_DEATH);
+	  THREAD_SETMEM(self, p_eventbuf.eventdata, self);
+	  __pthread_last_event = self;
+
+	  /* Now call the function to signal the event.  */
+	  __linuxthreads_death_event();
+	}
+    }
+  /* Say that we've terminated */
+  THREAD_SETMEM(self, p_terminated, 1);
+  /* See if someone is joining on us */
+  joining = THREAD_GETMEM(self, p_joining);
+  PDEBUG("joining = %p, pid=%d\n", joining, joining ? joining->p_pid : 0);
+  __pthread_unlock(THREAD_GETMEM(self, p_lock));
+  /* Restart joining thread if any */
+  if (joining != NULL) restart(joining);
+  /* If this is the initial thread, block until all threads have terminated.
+     If another thread calls exit, we'll be terminated from our signal
+     handler. */
+  if (self == __pthread_main_thread && __pthread_manager_request >= 0) {
+    request.req_thread = self;
+    request.req_kind = REQ_MAIN_THREAD_EXIT;
+    TEMP_FAILURE_RETRY(write(__pthread_manager_request,
+		(char *)&request, sizeof(request)));
+    suspend(self);
+    /* Main thread flushes stdio streams and runs atexit functions.
+     * It also calls a handler within LinuxThreads which sends a process exit
+     * request to the thread manager. */
+    exit(0);
+  }
+  /* Exit the process (but don't flush stdio streams, and don't run
+     atexit functions). */
+  _exit(0);
+}
+
+/* Function called by pthread_cancel to remove the thread from
+   waiting on a condition variable queue. */
+
+static int join_extricate_func(void *obj, pthread_descr th attribute_unused)
+{
+  volatile pthread_descr self = thread_self();
+  pthread_handle handle = obj;
+  pthread_descr jo;
+  int did_remove = 0;
+
+  __pthread_lock(&handle->h_lock, self);
+  jo = handle->h_descr;
+  did_remove = jo->p_joining != NULL;
+  jo->p_joining = NULL;
+  __pthread_unlock(&handle->h_lock);
+
+  return did_remove;
+}
+
+int pthread_join(pthread_t thread_id, void ** thread_return)
+{
+  volatile pthread_descr self = thread_self();
+  struct pthread_request request;
+  pthread_handle handle = thread_handle(thread_id);
+  pthread_descr th;
+  pthread_extricate_if extr;
+  int already_canceled = 0;
+  PDEBUG("\n");
+
+  /* Set up extrication interface */
+  extr.pu_object = handle;
+  extr.pu_extricate_func = join_extricate_func;
+
+  __pthread_lock(&handle->h_lock, self);
+  if (invalid_handle(handle, thread_id)) {
+    __pthread_unlock(&handle->h_lock);
+    return ESRCH;
+  }
+  th = handle->h_descr;
+  if (th == self) {
+    __pthread_unlock(&handle->h_lock);
+    return EDEADLK;
+  }
+  /* If detached or already joined, error */
+  if (th->p_detached || th->p_joining != NULL) {
+    __pthread_unlock(&handle->h_lock);
+    return EINVAL;
+  }
+  /* If not terminated yet, suspend ourselves. */
+  if (! th->p_terminated) {
+    /* Register extrication interface */
+    __pthread_set_own_extricate_if(self, &extr);
+    if (!(THREAD_GETMEM(self, p_canceled)
+	&& THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE))
+      th->p_joining = self;
+    else
+      already_canceled = 1;
+    __pthread_unlock(&handle->h_lock);
+
+    if (already_canceled) {
+      __pthread_set_own_extricate_if(self, 0);
+      __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+    }
+
+  PDEBUG("before suspend\n");
+    suspend(self);
+  PDEBUG("after suspend\n");
+    /* Deregister extrication interface */
+    __pthread_set_own_extricate_if(self, 0);
+
+    /* This is a cancellation point */
+    if (THREAD_GETMEM(self, p_woken_by_cancel)
+	&& THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
+      THREAD_SETMEM(self, p_woken_by_cancel, 0);
+      __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+    }
+    __pthread_lock(&handle->h_lock, self);
+  }
+  /* Get return value */
+  if (thread_return != NULL) *thread_return = th->p_retval;
+  __pthread_unlock(&handle->h_lock);
+  /* Send notification to thread manager */
+  if (__pthread_manager_request >= 0) {
+    request.req_thread = self;
+    request.req_kind = REQ_FREE;
+    request.req_args.free.thread_id = thread_id;
+    TEMP_FAILURE_RETRY(write(__pthread_manager_request,
+		(char *) &request, sizeof(request)));
+  }
+  return 0;
+}
+
+int pthread_detach(pthread_t thread_id)
+{
+  int terminated;
+  struct pthread_request request;
+  pthread_handle handle = thread_handle(thread_id);
+  pthread_descr th;
+
+  __pthread_lock(&handle->h_lock, NULL);
+  if (invalid_handle(handle, thread_id)) {
+    __pthread_unlock(&handle->h_lock);
+    return ESRCH;
+  }
+  th = handle->h_descr;
+  /* If already detached, error */
+  if (th->p_detached) {
+    __pthread_unlock(&handle->h_lock);
+    return EINVAL;
+  }
+  /* If already joining, don't do anything. */
+  if (th->p_joining != NULL) {
+    __pthread_unlock(&handle->h_lock);
+    return 0;
+  }
+  /* Mark as detached */
+  th->p_detached = 1;
+  terminated = th->p_terminated;
+  __pthread_unlock(&handle->h_lock);
+  /* If already terminated, notify thread manager to reclaim resources */
+  if (terminated && __pthread_manager_request >= 0) {
+    request.req_thread = thread_self();
+    request.req_kind = REQ_FREE;
+    request.req_args.free.thread_id = thread_id;
+    TEMP_FAILURE_RETRY(write(__pthread_manager_request,
+		(char *) &request, sizeof(request)));
+  }
+  return 0;
+}

+ 43 - 0
libpthread/linuxthreads.old/libc_pthread_init.c

@@ -0,0 +1,43 @@
+/* Copyright (C) 2002 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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <locale.h>
+#include <string.h>
+#include <linuxthreads.old/sysdeps/pthread/pthread-functions.h>
+
+
+int __libc_multiple_threads attribute_hidden __attribute__((nocommon));
+
+int * __libc_pthread_init (const struct pthread_functions *functions)
+{
+#ifdef SHARED
+  /* We copy the content of the variable pointed to by the FUNCTIONS
+     parameter to one in libc.so since this means access to the array
+     can be done with one memory access instead of two.  */
+  memcpy (&__libc_pthread_functions, functions,
+	  sizeof (__libc_pthread_functions));
+#endif
+
+#if !defined __UCLIBC_HAS_TLS__ && defined __UCLIBC_HAS_XLOCALE__
+  /* Initialize thread-locale current locale to point to the global one.
+     With __thread support, the variable's initializer takes care of this.  */
+  uselocale (LC_GLOBAL_LOCALE);
+#endif
+
+  return &__libc_multiple_threads;
+}

+ 0 - 0
libpthread/linuxthreads/linuxthreads.texi → libpthread/linuxthreads.old/linuxthreads.texi


+ 0 - 0
libpthread/linuxthreads/locale.c → libpthread/linuxthreads.old/locale.c


+ 42 - 0
libpthread/linuxthreads.old/lockfile.c

@@ -0,0 +1,42 @@
+/* lockfile - Handle locking and unlocking of stream.
+   Copyright (C) 1996, 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; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <pthread.h>
+
+extern __typeof(pthread_mutexattr_init) __pthread_mutexattr_init attribute_hidden;
+extern __typeof(pthread_mutexattr_settype) __pthread_mutexattr_settype attribute_hidden;
+extern __typeof(pthread_mutexattr_destroy) __pthread_mutexattr_destroy attribute_hidden;
+
+/* Note: glibc puts flockfile, funlockfile, and ftrylockfile in both
+ * libc and libpthread.  In uClibc, they are now in libc only.  */
+
+void __fresetlockfiles (void);
+void __fresetlockfiles (void)
+{
+  FILE *fp;
+  pthread_mutexattr_t attr;
+
+  __pthread_mutexattr_init(&attr);
+  __pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
+
+  for (fp = _stdio_openlist; fp != NULL; fp = fp->__nextopen)
+    __pthread_mutex_init(&fp->__lock, &attr);
+
+  __pthread_mutexattr_destroy(&attr);
+}

+ 933 - 0
libpthread/linuxthreads.old/manager.c

@@ -0,0 +1,933 @@
+/* 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.                 */
+
+/* The "thread manager" thread: manages creation and termination of threads */
+
+#include <features.h>
+#include <errno.h>
+#include <sched.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/poll.h>		/* for poll */
+#include <sys/mman.h>           /* for mmap */
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/wait.h>           /* for waitpid macros */
+
+#include "pthread.h"
+#include "internals.h"
+#include "spinlock.h"
+#include "restart.h"
+#include "semaphore.h"
+#include "debug.h" /* PDEBUG, added by StS */
+
+#ifndef THREAD_STACK_OFFSET
+#define THREAD_STACK_OFFSET 0
+#endif
+
+/* poll() is not supported in kernel <= 2.0, therefore is __NR_poll is
+ * not available, we assume an old Linux kernel is in use and we will
+ * use select() instead. */
+#include <sys/syscall.h>
+#ifndef __NR_poll
+# define USE_SELECT
+#endif
+
+libpthread_hidden_proto(waitpid)
+libpthread_hidden_proto(raise)
+
+/* Array of active threads. Entry 0 is reserved for the initial thread. */
+struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX] =
+{ { __LOCK_INITIALIZER, &__pthread_initial_thread, 0},
+  { __LOCK_INITIALIZER, &__pthread_manager_thread, 0}, /* All NULLs */ };
+
+/* For debugging purposes put the maximum number of threads in a variable.  */
+const int __linuxthreads_pthread_threads_max = PTHREAD_THREADS_MAX;
+
+/* Indicate whether at least one thread has a user-defined stack (if 1),
+   or if all threads have stacks supplied by LinuxThreads (if 0). */
+int __pthread_nonstandard_stacks;
+
+/* Number of active entries in __pthread_handles (used by gdb) */
+volatile int __pthread_handles_num = 2;
+
+/* Whether to use debugger additional actions for thread creation
+   (set to 1 by gdb) */
+volatile int __pthread_threads_debug;
+
+/* Globally enabled events.  */
+volatile td_thr_events_t __pthread_threads_events;
+
+/* Pointer to thread descriptor with last event.  */
+volatile pthread_descr __pthread_last_event;
+
+/* Mapping from stack segment to thread descriptor. */
+/* Stack segment numbers are also indices into the __pthread_handles array. */
+/* Stack segment number 0 is reserved for the initial thread. */
+
+static __inline__ pthread_descr thread_segment(int seg)
+{
+  return (pthread_descr)(THREAD_STACK_START_ADDRESS - (seg - 1) * STACK_SIZE)
+         - 1;
+}
+
+/* Flag set in signal handler to record child termination */
+
+static volatile int terminated_children = 0;
+
+/* Flag set when the initial thread is blocked on pthread_exit waiting
+   for all other threads to terminate */
+
+static int main_thread_exiting = 0;
+
+/* Counter used to generate unique thread identifier.
+   Thread identifier is pthread_threads_counter + segment. */
+
+static pthread_t pthread_threads_counter = 0;
+
+/* Forward declarations */
+
+static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
+                                 void * (*start_routine)(void *), void *arg,
+                                 sigset_t *mask, int father_pid,
+				 int report_events,
+				 td_thr_events_t *event_maskp);
+static void pthread_handle_free(pthread_t th_id);
+static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode) attribute_noreturn;
+static void pthread_reap_children(void);
+static void pthread_kill_all_threads(int sig, int main_thread_also);
+
+/* The server thread managing requests for thread creation and termination */
+
+int attribute_noreturn __pthread_manager(void *arg)
+{
+  int reqfd = (int) (long int) arg;
+#ifdef USE_SELECT
+  struct timeval tv;
+  fd_set fd;
+#else
+  struct pollfd ufd;
+#endif
+  sigset_t manager_mask;
+  int n;
+  struct pthread_request request;
+
+  /* If we have special thread_self processing, initialize it.  */
+#ifdef INIT_THREAD_SELF
+  INIT_THREAD_SELF(&__pthread_manager_thread, 1);
+#endif
+  /* Set the error variable.  */
+  __pthread_manager_thread.p_errnop = &__pthread_manager_thread.p_errno;
+  __pthread_manager_thread.p_h_errnop = &__pthread_manager_thread.p_h_errno;
+
+#ifdef __UCLIBC_HAS_XLOCALE__
+  /* Initialize thread's locale to the global locale. */
+  __pthread_manager_thread.locale = __global_locale;
+#endif /* __UCLIBC_HAS_XLOCALE__ */
+
+  /* Block all signals except __pthread_sig_cancel and SIGTRAP */
+  __sigfillset(&manager_mask);
+  sigdelset(&manager_mask, __pthread_sig_cancel); /* for thread termination */
+  sigdelset(&manager_mask, SIGTRAP);            /* for debugging purposes */
+  if (__pthread_threads_debug && __pthread_sig_debug > 0)
+      sigdelset(&manager_mask, __pthread_sig_debug);
+  sigprocmask(SIG_SETMASK, &manager_mask, NULL);
+  /* Raise our priority to match that of main thread */
+  __pthread_manager_adjust_prio(__pthread_main_thread->p_priority);
+  /* Synchronize debugging of the thread manager */
+  n = TEMP_FAILURE_RETRY(read(reqfd, (char *)&request,
+				     sizeof(request)));
+#ifndef USE_SELECT
+  ufd.fd = reqfd;
+  ufd.events = POLLIN;
+#endif
+  /* Enter server loop */
+  while(1) {
+#ifdef USE_SELECT
+    tv.tv_sec = 2;
+    tv.tv_usec = 0;
+    FD_ZERO (&fd);
+    FD_SET (reqfd, &fd);
+    n = select (reqfd + 1, &fd, NULL, NULL, &tv);
+#else
+    PDEBUG("before poll\n");
+    n = poll(&ufd, 1, 2000);
+    PDEBUG("after poll\n");
+#endif
+    /* Check for termination of the main thread */
+    if (getppid() == 1) {
+      pthread_kill_all_threads(SIGKILL, 0);
+      _exit(0);
+    }
+    /* Check for dead children */
+    if (terminated_children) {
+      terminated_children = 0;
+      pthread_reap_children();
+    }
+    /* Read and execute request */
+#ifdef USE_SELECT
+    if (n == 1)
+#else
+    if (n == 1 && (ufd.revents & POLLIN))
+#endif
+    {
+
+      PDEBUG("before read\n");
+      n = read(reqfd, (char *)&request, sizeof(request));
+      PDEBUG("after read, n=%d\n", n);
+      switch(request.req_kind) {
+      case REQ_CREATE:
+        PDEBUG("got REQ_CREATE\n");
+        request.req_thread->p_retcode =
+          pthread_handle_create((pthread_t *) &request.req_thread->p_retval,
+                                request.req_args.create.attr,
+                                request.req_args.create.fn,
+                                request.req_args.create.arg,
+                                &request.req_args.create.mask,
+                                request.req_thread->p_pid,
+                                request.req_thread->p_report_events,
+                                &request.req_thread->p_eventbuf.eventmask);
+        PDEBUG("restarting %p\n", request.req_thread);
+        restart(request.req_thread);
+        break;
+      case REQ_FREE:
+        PDEBUG("got REQ_FREE\n");
+        pthread_handle_free(request.req_args.free.thread_id);
+        break;
+      case REQ_PROCESS_EXIT:
+        PDEBUG("got REQ_PROCESS_EXIT from %p, exit code = %d\n",
+        request.req_thread, request.req_args.exit.code);
+        pthread_handle_exit(request.req_thread,
+                            request.req_args.exit.code);
+        break;
+      case REQ_MAIN_THREAD_EXIT:
+        PDEBUG("got REQ_MAIN_THREAD_EXIT\n");
+        main_thread_exiting = 1;
+	/* Reap children in case all other threads died and the signal handler
+	   went off before we set main_thread_exiting to 1, and therefore did
+	   not do REQ_KICK. */
+	pthread_reap_children();
+
+        if (__pthread_main_thread->p_nextlive == __pthread_main_thread) {
+          restart(__pthread_main_thread);
+	  /* The main thread will now call exit() which will trigger an
+	     __on_exit handler, which in turn will send REQ_PROCESS_EXIT
+	     to the thread manager. In case you are wondering how the
+	     manager terminates from its loop here. */
+	}
+        break;
+      case REQ_POST:
+        PDEBUG("got REQ_POST\n");
+        sem_post(request.req_args.post);
+        break;
+      case REQ_DEBUG:
+        PDEBUG("got REQ_DEBUG\n");
+	/* Make gdb aware of new thread and gdb will restart the
+	   new thread when it is ready to handle the new thread. */
+	if (__pthread_threads_debug && __pthread_sig_debug > 0) {
+	  PDEBUG("about to call raise(__pthread_sig_debug)\n");
+	  raise(__pthread_sig_debug);
+	}
+      case REQ_KICK:
+	/* This is just a prod to get the manager to reap some
+	   threads right away, avoiding a potential delay at shutdown. */
+	break;
+      }
+    }
+  }
+}
+
+int attribute_noreturn __pthread_manager_event(void *arg)
+{
+  /* If we have special thread_self processing, initialize it.  */
+#ifdef INIT_THREAD_SELF
+  INIT_THREAD_SELF(&__pthread_manager_thread, 1);
+#endif
+
+  /* Get the lock the manager will free once all is correctly set up.  */
+  __pthread_lock (THREAD_GETMEM((&__pthread_manager_thread), p_lock), NULL);
+  /* Free it immediately.  */
+  __pthread_unlock (THREAD_GETMEM((&__pthread_manager_thread), p_lock));
+
+  __pthread_manager(arg);
+}
+
+/* Process creation */
+static int
+attribute_noreturn
+pthread_start_thread(void *arg)
+{
+  pthread_descr self = (pthread_descr) arg;
+  struct pthread_request request;
+  void * outcome;
+  /* Initialize special thread_self processing, if any.  */
+#ifdef INIT_THREAD_SELF
+  INIT_THREAD_SELF(self, self->p_nr);
+#endif
+  PDEBUG("\n");
+  /* Make sure our pid field is initialized, just in case we get there
+     before our father has initialized it. */
+  THREAD_SETMEM(self, p_pid, getpid());
+  /* Initial signal mask is that of the creating thread. (Otherwise,
+     we'd just inherit the mask of the thread manager.) */
+  sigprocmask(SIG_SETMASK, &self->p_start_args.mask, NULL);
+  /* Set the scheduling policy and priority for the new thread, if needed */
+  if (THREAD_GETMEM(self, p_start_args.schedpolicy) >= 0)
+    /* Explicit scheduling attributes were provided: apply them */
+    sched_setscheduler(THREAD_GETMEM(self, p_pid),
+			 THREAD_GETMEM(self, p_start_args.schedpolicy),
+                         &self->p_start_args.schedparam);
+  else if (__pthread_manager_thread.p_priority > 0)
+    /* Default scheduling required, but thread manager runs in realtime
+       scheduling: switch new thread to SCHED_OTHER policy */
+    {
+      struct sched_param default_params;
+      default_params.sched_priority = 0;
+      sched_setscheduler(THREAD_GETMEM(self, p_pid),
+                           SCHED_OTHER, &default_params);
+    }
+  /* Make gdb aware of new thread */
+  if (__pthread_threads_debug && __pthread_sig_debug > 0) {
+    request.req_thread = self;
+    request.req_kind = REQ_DEBUG;
+    TEMP_FAILURE_RETRY(write(__pthread_manager_request,
+		(char *) &request, sizeof(request)));
+    suspend(self);
+  }
+  /* Run the thread code */
+  outcome = self->p_start_args.start_routine(THREAD_GETMEM(self,
+							   p_start_args.arg));
+  /* Exit with the given return value */
+  __pthread_do_exit(outcome, CURRENT_STACK_FRAME);
+}
+
+static int
+attribute_noreturn
+pthread_start_thread_event(void *arg)
+{
+  pthread_descr self = (pthread_descr) arg;
+
+#ifdef INIT_THREAD_SELF
+  INIT_THREAD_SELF(self, self->p_nr);
+#endif
+  /* Make sure our pid field is initialized, just in case we get there
+     before our father has initialized it. */
+  THREAD_SETMEM(self, p_pid, getpid());
+  /* Get the lock the manager will free once all is correctly set up.  */
+  __pthread_lock (THREAD_GETMEM(self, p_lock), NULL);
+  /* Free it immediately.  */
+  __pthread_unlock (THREAD_GETMEM(self, p_lock));
+
+  /* Continue with the real function.  */
+  pthread_start_thread (arg);
+}
+
+static int pthread_allocate_stack(const pthread_attr_t *attr,
+                                  pthread_descr default_new_thread,
+                                  int pagesize,
+                                  pthread_descr * out_new_thread,
+                                  char ** out_new_thread_bottom,
+                                  char ** out_guardaddr,
+                                  size_t * out_guardsize)
+{
+  pthread_descr new_thread;
+  char * new_thread_bottom;
+  char * guardaddr;
+  size_t stacksize, guardsize;
+
+  if (attr != NULL && attr->__stackaddr_set)
+    {
+      /* The user provided a stack. */
+      new_thread = (pthread_descr) ((long)(attr->__stackaddr) & -sizeof(void *)) - 1;
+      new_thread_bottom = (char *) attr->__stackaddr - attr->__stacksize;
+      guardaddr = NULL;
+      guardsize = 0;
+      __pthread_nonstandard_stacks = 1;
+#ifndef __ARCH_USE_MMU__
+      /* check the initial thread stack boundaries so they don't overlap */
+      NOMMU_INITIAL_THREAD_BOUNDS((char *) new_thread, (char *) new_thread_bottom);
+
+      PDEBUG("initial stack: bos=%p, tos=%p\n", __pthread_initial_thread_bos,
+            __pthread_initial_thread_tos);
+#endif
+    }
+  else
+    {
+#ifdef __ARCH_USE_MMU__
+      stacksize = STACK_SIZE - pagesize;
+      if (attr != NULL)
+        stacksize = MIN(stacksize, roundup(attr->__stacksize, pagesize));
+      /* Allocate space for stack and thread descriptor at default address */
+      new_thread = default_new_thread;
+      new_thread_bottom = (char *) (new_thread + 1) - stacksize;
+      if (mmap((caddr_t)((char *)(new_thread + 1) - INITIAL_STACK_SIZE),
+               INITIAL_STACK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
+               MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_GROWSDOWN,
+               -1, 0) == MAP_FAILED)
+        /* Bad luck, this segment is already mapped. */
+        return -1;
+      /* We manage to get a stack.  Now see whether we need a guard
+         and allocate it if necessary.  Notice that the default
+         attributes (stack_size = STACK_SIZE - pagesize) do not need
+	 a guard page, since the RLIMIT_STACK soft limit prevents stacks
+	 from running into one another. */
+      if (stacksize == (size_t) (STACK_SIZE - pagesize))
+        {
+          /* We don't need a guard page. */
+          guardaddr = NULL;
+          guardsize = 0;
+        }
+      else
+        {
+          /* Put a bad page at the bottom of the stack */
+          guardsize = attr->__guardsize;
+          guardaddr = (void *)new_thread_bottom - guardsize;
+          if (mmap((caddr_t) guardaddr, guardsize, 0, MAP_FIXED, -1, 0)
+              == MAP_FAILED)
+            {
+              /* We don't make this an error.  */
+              guardaddr = NULL;
+              guardsize = 0;
+            }
+        }
+#else
+      /* We cannot mmap to this huge chunk of stack space when we don't have
+       * an MMU. Pretend we are using a user provided stack even if there was
+       * none provided by the user. Thus, we get around the mmap and reservation
+       * of a huge stack segment. -StS */
+
+      stacksize = INITIAL_STACK_SIZE;
+      /* The user may want to use a non-default stacksize */
+      if (attr != NULL)
+	{
+	  stacksize = attr->__stacksize;
+	}
+
+      /* malloc a stack - memory from the bottom up */
+      if ((new_thread_bottom = malloc(stacksize)) == NULL)
+	{
+	  /* bad luck, we cannot malloc any more */
+	  return -1 ;
+	}
+      PDEBUG("malloced chunk: base=%p, size=0x%04x\n", new_thread_bottom, stacksize);
+
+      /* Set up the pointers. new_thread marks the TOP of the stack frame and
+       * the address of the pthread_descr struct at the same time. Therefore we
+       * must account for its size and fit it in the malloc()'ed block. The
+       * value of `new_thread' is then passed to clone() as the stack argument.
+       *
+       *               ^ +------------------------+
+       *               | |  pthread_descr struct  |
+       *               | +------------------------+  <- new_thread
+       * malloc block  | |                        |
+       *               | |  thread stack          |
+       *               | |                        |
+       *               v +------------------------+  <- new_thread_bottom
+       *
+       * Note: The calculated value of new_thread must be word aligned otherwise
+       * the kernel chokes on a non-aligned stack frame. Choose the lower
+       * available word boundary.
+       */
+      new_thread = ((pthread_descr) ((int)(new_thread_bottom + stacksize) & -sizeof(void*))) - 1;
+      guardaddr = NULL;
+      guardsize = 0;
+
+      PDEBUG("thread stack: bos=%p, tos=%p\n", new_thread_bottom, new_thread);
+
+      /* check the initial thread stack boundaries so they don't overlap */
+      NOMMU_INITIAL_THREAD_BOUNDS((char *) new_thread, (char *) new_thread_bottom);
+
+      PDEBUG("initial stack: bos=%p, tos=%p\n", __pthread_initial_thread_bos,
+	     __pthread_initial_thread_tos);
+
+      /* on non-MMU systems we always have non-standard stack frames */
+      __pthread_nonstandard_stacks = 1;
+
+#endif /* __ARCH_USE_MMU__ */
+    }
+
+  /* Clear the thread data structure.  */
+  memset (new_thread, '\0', sizeof (*new_thread));
+  *out_new_thread = new_thread;
+  *out_new_thread_bottom = new_thread_bottom;
+  *out_guardaddr = guardaddr;
+  *out_guardsize = guardsize;
+  return 0;
+}
+
+static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
+				 void * (*start_routine)(void *), void *arg,
+				 sigset_t * mask, int father_pid,
+				 int report_events,
+				 td_thr_events_t *event_maskp)
+{
+  size_t sseg;
+  int pid;
+  pthread_descr new_thread;
+  char * new_thread_bottom;
+  char * new_thread_top;
+  pthread_t new_thread_id;
+  char *guardaddr = NULL;
+  size_t guardsize = 0;
+  int pagesize = getpagesize();
+  int saved_errno = 0;
+
+  /* First check whether we have to change the policy and if yes, whether
+     we can  do this.  Normally this should be done by examining the
+     return value of the sched_setscheduler call in pthread_start_thread
+     but this is hard to implement.  FIXME  */
+  if (attr != NULL && attr->__schedpolicy != SCHED_OTHER && geteuid () != 0)
+    return EPERM;
+  /* Find a free segment for the thread, and allocate a stack if needed */
+  for (sseg = 2; ; sseg++)
+    {
+      if (sseg >= PTHREAD_THREADS_MAX)
+	return EAGAIN;
+      if (__pthread_handles[sseg].h_descr != NULL)
+	continue;
+      if (pthread_allocate_stack(attr, thread_segment(sseg), pagesize,
+                                 &new_thread, &new_thread_bottom,
+                                 &guardaddr, &guardsize) == 0)
+        break;
+#ifndef __ARCH_USE_MMU__
+      else
+        /* When there is MMU, mmap () is used to allocate the stack. If one
+         * segment is already mapped, we should continue to see if we can
+         * use the next one. However, when there is no MMU, malloc () is used.
+         * It's waste of CPU cycles to continue to try if it fails.  */
+        return EAGAIN;
+#endif
+    }
+  __pthread_handles_num++;
+  /* Allocate new thread identifier */
+  pthread_threads_counter += PTHREAD_THREADS_MAX;
+  new_thread_id = sseg + pthread_threads_counter;
+  /* Initialize the thread descriptor.  Elements which have to be
+     initialized to zero already have this value.  */
+  new_thread->p_tid = new_thread_id;
+  new_thread->p_lock = &(__pthread_handles[sseg].h_lock);
+  new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE;
+  new_thread->p_canceltype = PTHREAD_CANCEL_DEFERRED;
+  new_thread->p_errnop = &new_thread->p_errno;
+  new_thread->p_h_errnop = &new_thread->p_h_errno;
+#ifdef __UCLIBC_HAS_XLOCALE__
+  /* Initialize thread's locale to the global locale. */
+  new_thread->locale = __global_locale;
+#endif /* __UCLIBC_HAS_XLOCALE__ */
+  new_thread->p_guardaddr = guardaddr;
+  new_thread->p_guardsize = guardsize;
+  new_thread->p_self = new_thread;
+  new_thread->p_nr = sseg;
+  /* Initialize the thread handle */
+  __pthread_init_lock(&__pthread_handles[sseg].h_lock);
+  __pthread_handles[sseg].h_descr = new_thread;
+  __pthread_handles[sseg].h_bottom = new_thread_bottom;
+  /* Determine scheduling parameters for the thread */
+  new_thread->p_start_args.schedpolicy = -1;
+  if (attr != NULL) {
+    new_thread->p_detached = attr->__detachstate;
+    new_thread->p_userstack = attr->__stackaddr_set;
+
+    switch(attr->__inheritsched) {
+    case PTHREAD_EXPLICIT_SCHED:
+      new_thread->p_start_args.schedpolicy = attr->__schedpolicy;
+      memcpy (&new_thread->p_start_args.schedparam, &attr->__schedparam,
+	      sizeof (struct sched_param));
+      break;
+    case PTHREAD_INHERIT_SCHED:
+      new_thread->p_start_args.schedpolicy = sched_getscheduler(father_pid);
+      sched_getparam(father_pid, &new_thread->p_start_args.schedparam);
+      break;
+    }
+    new_thread->p_priority =
+      new_thread->p_start_args.schedparam.sched_priority;
+  }
+  /* Finish setting up arguments to pthread_start_thread */
+  new_thread->p_start_args.start_routine = start_routine;
+  new_thread->p_start_args.arg = arg;
+  new_thread->p_start_args.mask = *mask;
+  /* Raise priority of thread manager if needed */
+  __pthread_manager_adjust_prio(new_thread->p_priority);
+  /* Do the cloning.  We have to use two different functions depending
+     on whether we are debugging or not.  */
+  pid = 0;     /* Note that the thread never can have PID zero.  */
+  new_thread_top = ((char *)new_thread - THREAD_STACK_OFFSET);
+
+  /* ******************************************************** */
+  /*  This code was moved from below to cope with running threads
+   *  on uClinux systems.  See comment below...
+   * Insert new thread in doubly linked list of active threads */
+  new_thread->p_prevlive = __pthread_main_thread;
+  new_thread->p_nextlive = __pthread_main_thread->p_nextlive;
+  __pthread_main_thread->p_nextlive->p_prevlive = new_thread;
+  __pthread_main_thread->p_nextlive = new_thread;
+  /* ********************************************************* */
+
+  if (report_events)
+    {
+      /* See whether the TD_CREATE event bit is set in any of the
+         masks.  */
+      int idx = __td_eventword (TD_CREATE);
+      uint32_t m = __td_eventmask (TD_CREATE);
+
+      if ((m & (__pthread_threads_events.event_bits[idx]
+		   | event_maskp->event_bits[idx])) != 0)
+	{
+	  /* Lock the mutex the child will use now so that it will stop.  */
+	  __pthread_lock(new_thread->p_lock, NULL);
+
+	  /* We have to report this event.  */
+#ifdef __ia64__
+	  pid = __clone2(pthread_start_thread_event, new_thread_top,
+			new_thread_top - new_thread_bottom,
+			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+			__pthread_sig_cancel, new_thread);
+#else
+	  pid = clone(pthread_start_thread_event, new_thread_top,
+			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+			__pthread_sig_cancel, new_thread);
+#endif
+
+	  saved_errno = errno;
+	  if (pid != -1)
+	    {
+	      /* Now fill in the information about the new thread in
+	         the newly created thread's data structure.  We cannot let
+	         the new thread do this since we don't know whether it was
+	         already scheduled when we send the event.  */
+	      new_thread->p_eventbuf.eventdata = new_thread;
+	      new_thread->p_eventbuf.eventnum = TD_CREATE;
+	      __pthread_last_event = new_thread;
+
+	      /* We have to set the PID here since the callback function
+		 in the debug library will need it and we cannot guarantee
+		 the child got scheduled before the debugger.  */
+	      new_thread->p_pid = pid;
+
+	      /* Now call the function which signals the event.  */
+	      __linuxthreads_create_event ();
+
+	      /* Now restart the thread.  */
+	      __pthread_unlock(new_thread->p_lock);
+	    }
+	}
+    }
+  if (pid == 0)
+    {
+      PDEBUG("cloning new_thread = %p\n", new_thread);
+#ifdef __ia64__
+      pid = __clone2(pthread_start_thread, new_thread_top,
+		    new_thread_top - new_thread_bottom,
+		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+		    __pthread_sig_cancel, new_thread);
+#else
+      pid = clone(pthread_start_thread, new_thread_top,
+		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+		    __pthread_sig_cancel, new_thread);
+#endif
+      saved_errno = errno;
+    }
+  /* Check if cloning succeeded */
+  if (pid == -1) {
+    /********************************************************
+     * Code inserted to remove the thread from our list of active
+     * threads in case of failure (needed to cope with uClinux),
+     * See comment below. */
+    new_thread->p_nextlive->p_prevlive = new_thread->p_prevlive;
+    new_thread->p_prevlive->p_nextlive = new_thread->p_nextlive;
+    /********************************************************/
+
+    /* Free the stack if we allocated it */
+    if (attr == NULL || !attr->__stackaddr_set)
+      {
+#ifdef __ARCH_USE_MMU__
+	if (new_thread->p_guardsize != 0)
+	  munmap(new_thread->p_guardaddr, new_thread->p_guardsize);
+	munmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE),
+	       INITIAL_STACK_SIZE);
+#else
+	free(new_thread_bottom);
+#endif /* __ARCH_USE_MMU__ */
+      }
+    __pthread_handles[sseg].h_descr = NULL;
+    __pthread_handles[sseg].h_bottom = NULL;
+    __pthread_handles_num--;
+    return saved_errno;
+  }
+  PDEBUG("new thread pid = %d\n", pid);
+
+#if 0
+  /* ***********************************************************
+   This code has been moved before the call to clone().  In uClinux,
+   the use of wait on a semaphore is dependant upon that the child so
+   the child must be in the active threads list. This list is used in
+   pthread_find_self() to get the pthread_descr of self. So, if the
+   child calls sem_wait before this code is executed , it will hang
+   forever and initial_thread will instead be posted by a sem_post
+   call. */
+
+  /* Insert new thread in doubly linked list of active threads */
+  new_thread->p_prevlive = __pthread_main_thread;
+  new_thread->p_nextlive = __pthread_main_thread->p_nextlive;
+  __pthread_main_thread->p_nextlive->p_prevlive = new_thread;
+  __pthread_main_thread->p_nextlive = new_thread;
+  /************************************************************/
+#endif
+
+  /* Set pid field of the new thread, in case we get there before the
+     child starts. */
+  new_thread->p_pid = pid;
+  /* We're all set */
+  *thread = new_thread_id;
+  return 0;
+}
+
+
+/* Try to free the resources of a thread when requested by pthread_join
+   or pthread_detach on a terminated thread. */
+
+static void pthread_free(pthread_descr th)
+{
+  pthread_handle handle;
+  pthread_readlock_info *iter, *next;
+#ifndef __ARCH_USE_MMU__
+  char *h_bottom_save;
+#endif
+
+  /* Make the handle invalid */
+  handle =  thread_handle(th->p_tid);
+  __pthread_lock(&handle->h_lock, NULL);
+#ifndef __ARCH_USE_MMU__
+  h_bottom_save = handle->h_bottom;
+#endif
+  handle->h_descr = NULL;
+  handle->h_bottom = (char *)(-1L);
+  __pthread_unlock(&handle->h_lock);
+#ifdef FREE_THREAD_SELF
+  FREE_THREAD_SELF(th, th->p_nr);
+#endif
+  /* One fewer threads in __pthread_handles */
+  __pthread_handles_num--;
+
+  /* Destroy read lock list, and list of free read lock structures.
+     If the former is not empty, it means the thread exited while
+     holding read locks! */
+
+  for (iter = th->p_readlock_list; iter != NULL; iter = next)
+    {
+      next = iter->pr_next;
+      free(iter);
+    }
+
+  for (iter = th->p_readlock_free; iter != NULL; iter = next)
+    {
+      next = iter->pr_next;
+      free(iter);
+    }
+
+  /* If initial thread, nothing to free */
+  if (th == &__pthread_initial_thread) return;
+  if (!th->p_userstack)
+    {
+#ifdef __ARCH_USE_MMU__
+      /* Free the stack and thread descriptor area */
+      if (th->p_guardsize != 0)
+	munmap(th->p_guardaddr, th->p_guardsize);
+      munmap((caddr_t) ((char *)(th+1) - STACK_SIZE), STACK_SIZE);
+#else
+      /* For non-MMU systems we always malloc the stack, so free it here. -StS */
+      free(h_bottom_save);
+#endif /* __ARCH_USE_MMU__ */
+    }
+}
+
+/* Handle threads that have exited */
+
+static void pthread_exited(pid_t pid)
+{
+  pthread_descr th;
+  int detached;
+  /* Find thread with that pid */
+  for (th = __pthread_main_thread->p_nextlive;
+       th != __pthread_main_thread;
+       th = th->p_nextlive) {
+    if (th->p_pid == pid) {
+      /* Remove thread from list of active threads */
+      th->p_nextlive->p_prevlive = th->p_prevlive;
+      th->p_prevlive->p_nextlive = th->p_nextlive;
+      /* Mark thread as exited, and if detached, free its resources */
+      __pthread_lock(th->p_lock, NULL);
+      th->p_exited = 1;
+      /* If we have to signal this event do it now.  */
+      if (th->p_report_events)
+	{
+	  /* See whether TD_REAP is in any of the mask.  */
+	  int idx = __td_eventword (TD_REAP);
+	  uint32_t mask = __td_eventmask (TD_REAP);
+
+	  if ((mask & (__pthread_threads_events.event_bits[idx]
+		       | th->p_eventbuf.eventmask.event_bits[idx])) != 0)
+	    {
+	      /* Yep, we have to signal the reapage.  */
+	      th->p_eventbuf.eventnum = TD_REAP;
+	      th->p_eventbuf.eventdata = th;
+	      __pthread_last_event = th;
+
+	      /* Now call the function to signal the event.  */
+	      __linuxthreads_reap_event();
+	    }
+	}
+      detached = th->p_detached;
+      __pthread_unlock(th->p_lock);
+      if (detached)
+	pthread_free(th);
+      break;
+    }
+  }
+  /* If all threads have exited and the main thread is pending on a
+     pthread_exit, wake up the main thread and terminate ourselves. */
+  if (main_thread_exiting &&
+      __pthread_main_thread->p_nextlive == __pthread_main_thread) {
+    restart(__pthread_main_thread);
+    /* Same logic as REQ_MAIN_THREAD_EXIT. */
+  }
+}
+
+static void pthread_reap_children(void)
+{
+  pid_t pid;
+  int status;
+  PDEBUG("\n");
+
+  while ((pid = waitpid(-1, &status, WNOHANG | __WCLONE)) > 0) {
+    pthread_exited(pid);
+    if (WIFSIGNALED(status)) {
+      /* If a thread died due to a signal, send the same signal to
+         all other threads, including the main thread. */
+      pthread_kill_all_threads(WTERMSIG(status), 1);
+      _exit(0);
+    }
+  }
+}
+
+/* Try to free the resources of a thread when requested by pthread_join
+   or pthread_detach on a terminated thread. */
+
+static void pthread_handle_free(pthread_t th_id)
+{
+  pthread_handle handle = thread_handle(th_id);
+  pthread_descr th;
+
+  __pthread_lock(&handle->h_lock, NULL);
+  if (invalid_handle(handle, th_id)) {
+    /* pthread_reap_children has deallocated the thread already,
+       nothing needs to be done */
+    __pthread_unlock(&handle->h_lock);
+    return;
+  }
+  th = handle->h_descr;
+  if (th->p_exited) {
+    __pthread_unlock(&handle->h_lock);
+    pthread_free(th);
+  } else {
+    /* The Unix process of the thread is still running.
+       Mark the thread as detached so that the thread manager will
+       deallocate its resources when the Unix process exits. */
+    th->p_detached = 1;
+    __pthread_unlock(&handle->h_lock);
+  }
+}
+
+/* Send a signal to all running threads */
+
+static void pthread_kill_all_threads(int sig, int main_thread_also)
+{
+  pthread_descr th;
+  for (th = __pthread_main_thread->p_nextlive;
+       th != __pthread_main_thread;
+       th = th->p_nextlive) {
+    kill(th->p_pid, sig);
+  }
+  if (main_thread_also) {
+    kill(__pthread_main_thread->p_pid, sig);
+  }
+}
+
+/* Process-wide exit() */
+
+static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode)
+{
+  pthread_descr th;
+  __pthread_exit_requested = 1;
+  __pthread_exit_code = exitcode;
+  /* Send the CANCEL signal to all running threads, including the main
+     thread, but excluding the thread from which the exit request originated
+     (that thread must complete the exit, e.g. calling atexit functions
+     and flushing stdio buffers). */
+  for (th = issuing_thread->p_nextlive;
+       th != issuing_thread;
+       th = th->p_nextlive) {
+    kill(th->p_pid, __pthread_sig_cancel);
+  }
+  /* Now, wait for all these threads, so that they don't become zombies
+     and their times are properly added to the thread manager's times. */
+  for (th = issuing_thread->p_nextlive;
+       th != issuing_thread;
+       th = th->p_nextlive) {
+    waitpid(th->p_pid, NULL, __WCLONE);
+  }
+  restart(issuing_thread);
+  _exit(0);
+}
+
+/* Handler for __pthread_sig_cancel in thread manager thread */
+
+void __pthread_manager_sighandler(int sig attribute_unused)
+{
+    int kick_manager = terminated_children == 0 && main_thread_exiting;
+    terminated_children = 1;
+
+    /* If the main thread is terminating, kick the thread manager loop
+       each time some threads terminate. This eliminates a two second
+       shutdown delay caused by the thread manager sleeping in the
+       call to __poll(). Instead, the thread manager is kicked into
+       action, reaps the outstanding threads and resumes the main thread
+       so that it can complete the shutdown. */
+
+    if (kick_manager) {
+	struct pthread_request request;
+	request.req_thread = 0;
+	request.req_kind = REQ_KICK;
+	TEMP_FAILURE_RETRY(write(__pthread_manager_request,
+		    (char *) &request, sizeof(request)));
+    }
+}
+
+/* Adjust priority of thread manager so that it always run at a priority
+   higher than all threads */
+
+void __pthread_manager_adjust_prio(int thread_prio)
+{
+  struct sched_param param;
+
+  if (thread_prio <= __pthread_manager_thread.p_priority) return;
+  param.sched_priority =
+    thread_prio < sched_get_priority_max(SCHED_FIFO)
+    ? thread_prio + 1 : thread_prio;
+  sched_setscheduler(__pthread_manager_thread.p_pid, SCHED_FIFO, &param);
+  __pthread_manager_thread.p_priority = thread_prio;
+}

+ 362 - 0
libpthread/linuxthreads.old/mutex.c

@@ -0,0 +1,362 @@
+/* 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.                 */
+
+/* Mutexes */
+
+#include <errno.h>
+#include <sched.h>
+#include <stddef.h>
+#include <limits.h>
+#include "pthread.h"
+#include "internals.h"
+#include "spinlock.h"
+#include "queue.h"
+#include "restart.h"
+
+int attribute_hidden __pthread_mutex_init(pthread_mutex_t * mutex,
+                       const pthread_mutexattr_t * mutex_attr)
+{
+  __pthread_init_lock(&mutex->__m_lock);
+  mutex->__m_kind =
+    mutex_attr == NULL ? PTHREAD_MUTEX_TIMED_NP : mutex_attr->__mutexkind;
+  mutex->__m_count = 0;
+  mutex->__m_owner = NULL;
+  return 0;
+}
+strong_alias (__pthread_mutex_init, pthread_mutex_init)
+
+int attribute_hidden __pthread_mutex_destroy(pthread_mutex_t * mutex)
+{
+  switch (mutex->__m_kind) {
+  case PTHREAD_MUTEX_ADAPTIVE_NP:
+  case PTHREAD_MUTEX_RECURSIVE_NP:
+    if ((mutex->__m_lock.__status & 1) != 0)
+      return EBUSY;
+    return 0;
+  case PTHREAD_MUTEX_ERRORCHECK_NP:
+  case PTHREAD_MUTEX_TIMED_NP:
+    if (mutex->__m_lock.__status != 0)
+      return EBUSY;
+    return 0;
+  default:
+    return EINVAL;
+  }
+}
+strong_alias (__pthread_mutex_destroy, pthread_mutex_destroy)
+
+int attribute_hidden __pthread_mutex_trylock(pthread_mutex_t * mutex)
+{
+  pthread_descr self;
+  int retcode;
+
+  switch(mutex->__m_kind) {
+  case PTHREAD_MUTEX_ADAPTIVE_NP:
+    retcode = __pthread_trylock(&mutex->__m_lock);
+    return retcode;
+  case PTHREAD_MUTEX_RECURSIVE_NP:
+    self = thread_self();
+    if (mutex->__m_owner == self) {
+      mutex->__m_count++;
+      return 0;
+    }
+    retcode = __pthread_trylock(&mutex->__m_lock);
+    if (retcode == 0) {
+      mutex->__m_owner = self;
+      mutex->__m_count = 0;
+    }
+    return retcode;
+  case PTHREAD_MUTEX_ERRORCHECK_NP:
+    retcode = __pthread_alt_trylock(&mutex->__m_lock);
+    if (retcode == 0) {
+      mutex->__m_owner = thread_self();
+    }
+    return retcode;
+  case PTHREAD_MUTEX_TIMED_NP:
+    retcode = __pthread_alt_trylock(&mutex->__m_lock);
+    return retcode;
+  default:
+    return EINVAL;
+  }
+}
+strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock)
+
+int attribute_hidden __pthread_mutex_lock(pthread_mutex_t * mutex)
+{
+  pthread_descr self;
+
+  switch(mutex->__m_kind) {
+  case PTHREAD_MUTEX_ADAPTIVE_NP:
+    __pthread_lock(&mutex->__m_lock, NULL);
+    return 0;
+  case PTHREAD_MUTEX_RECURSIVE_NP:
+    self = thread_self();
+    if (mutex->__m_owner == self) {
+      mutex->__m_count++;
+      return 0;
+    }
+    __pthread_lock(&mutex->__m_lock, self);
+    mutex->__m_owner = self;
+    mutex->__m_count = 0;
+    return 0;
+  case PTHREAD_MUTEX_ERRORCHECK_NP:
+    self = thread_self();
+    if (mutex->__m_owner == self) return EDEADLK;
+    __pthread_alt_lock(&mutex->__m_lock, self);
+    mutex->__m_owner = self;
+    return 0;
+  case PTHREAD_MUTEX_TIMED_NP:
+    __pthread_alt_lock(&mutex->__m_lock, NULL);
+    return 0;
+  default:
+    return EINVAL;
+  }
+}
+strong_alias (__pthread_mutex_lock, pthread_mutex_lock)
+
+int pthread_mutex_timedlock (pthread_mutex_t *mutex,
+			       const struct timespec *abstime)
+{
+  pthread_descr self;
+  int res;
+
+  if (__builtin_expect (abstime->tv_nsec, 0) < 0
+      || __builtin_expect (abstime->tv_nsec, 0) >= 1000000000)
+    return EINVAL;
+
+  switch(mutex->__m_kind) {
+  case PTHREAD_MUTEX_ADAPTIVE_NP:
+    __pthread_lock(&mutex->__m_lock, NULL);
+    return 0;
+  case PTHREAD_MUTEX_RECURSIVE_NP:
+    self = thread_self();
+    if (mutex->__m_owner == self) {
+      mutex->__m_count++;
+      return 0;
+    }
+    __pthread_lock(&mutex->__m_lock, self);
+    mutex->__m_owner = self;
+    mutex->__m_count = 0;
+    return 0;
+  case PTHREAD_MUTEX_ERRORCHECK_NP:
+    self = thread_self();
+    if (mutex->__m_owner == self) return EDEADLK;
+    res = __pthread_alt_timedlock(&mutex->__m_lock, self, abstime);
+    if (res != 0)
+      {
+	mutex->__m_owner = self;
+	return 0;
+      }
+    return ETIMEDOUT;
+  case PTHREAD_MUTEX_TIMED_NP:
+    /* Only this type supports timed out lock. */
+    return (__pthread_alt_timedlock(&mutex->__m_lock, NULL, abstime)
+	    ? 0 : ETIMEDOUT);
+  default:
+    return EINVAL;
+  }
+}
+
+int attribute_hidden __pthread_mutex_unlock(pthread_mutex_t * mutex)
+{
+  switch (mutex->__m_kind) {
+  case PTHREAD_MUTEX_ADAPTIVE_NP:
+    __pthread_unlock(&mutex->__m_lock);
+    return 0;
+  case PTHREAD_MUTEX_RECURSIVE_NP:
+    if (mutex->__m_owner != thread_self())
+      return EPERM;
+    if (mutex->__m_count > 0) {
+      mutex->__m_count--;
+      return 0;
+    }
+    mutex->__m_owner = NULL;
+    __pthread_unlock(&mutex->__m_lock);
+    return 0;
+  case PTHREAD_MUTEX_ERRORCHECK_NP:
+    if (mutex->__m_owner != thread_self() || mutex->__m_lock.__status == 0)
+      return EPERM;
+    mutex->__m_owner = NULL;
+    __pthread_alt_unlock(&mutex->__m_lock);
+    return 0;
+  case PTHREAD_MUTEX_TIMED_NP:
+    __pthread_alt_unlock(&mutex->__m_lock);
+    return 0;
+  default:
+    return EINVAL;
+  }
+}
+strong_alias (__pthread_mutex_unlock, pthread_mutex_unlock)
+
+int attribute_hidden __pthread_mutexattr_init(pthread_mutexattr_t *attr)
+{
+  attr->__mutexkind = PTHREAD_MUTEX_TIMED_NP;
+  return 0;
+}
+strong_alias(__pthread_mutexattr_init,pthread_mutexattr_init)
+
+int attribute_hidden __pthread_mutexattr_destroy(pthread_mutexattr_t *attr attribute_unused)
+{
+  return 0;
+}
+strong_alias(__pthread_mutexattr_destroy,pthread_mutexattr_destroy)
+
+int attribute_hidden __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind)
+{
+  if (kind != PTHREAD_MUTEX_ADAPTIVE_NP
+      && kind != PTHREAD_MUTEX_RECURSIVE_NP
+      && kind != PTHREAD_MUTEX_ERRORCHECK_NP
+      && kind != PTHREAD_MUTEX_TIMED_NP)
+    return EINVAL;
+  attr->__mutexkind = kind;
+  return 0;
+}
+strong_alias(__pthread_mutexattr_settype,pthread_mutexattr_settype)
+strong_alias (__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np)
+weak_alias (__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np)
+
+int __pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind) attribute_hidden;
+int __pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind)
+{
+  *kind = attr->__mutexkind;
+  return 0;
+}
+weak_alias (__pthread_mutexattr_gettype, pthread_mutexattr_gettype)
+strong_alias (__pthread_mutexattr_gettype, __pthread_mutexattr_getkind_np)
+weak_alias (__pthread_mutexattr_getkind_np, pthread_mutexattr_getkind_np)
+
+int __pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr attribute_unused,
+				   int *pshared) attribute_hidden;
+int __pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr attribute_unused,
+				   int *pshared)
+{
+  *pshared = PTHREAD_PROCESS_PRIVATE;
+  return 0;
+}
+weak_alias (__pthread_mutexattr_getpshared, pthread_mutexattr_getpshared)
+
+int __pthread_mutexattr_setpshared (pthread_mutexattr_t *attr attribute_unused, int pshared) attribute_hidden;
+int __pthread_mutexattr_setpshared (pthread_mutexattr_t *attr attribute_unused, int pshared)
+{
+  if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
+    return EINVAL;
+
+  /* For now it is not possible to shared a conditional variable.  */
+  if (pshared != PTHREAD_PROCESS_PRIVATE)
+    return ENOSYS;
+
+  return 0;
+}
+weak_alias (__pthread_mutexattr_setpshared, pthread_mutexattr_setpshared)
+
+/* Once-only execution */
+
+static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t once_finished = PTHREAD_COND_INITIALIZER;
+static int fork_generation = 0;	/* Child process increments this after fork. */
+
+enum { NEVER = 0, IN_PROGRESS = 1, DONE = 2 };
+
+/* If a thread is canceled while calling the init_routine out of
+   pthread once, this handler will reset the once_control variable
+   to the NEVER state. */
+
+static void pthread_once_cancelhandler(void *arg)
+{
+    pthread_once_t *once_control = arg;
+
+    __pthread_mutex_lock(&once_masterlock);
+    *once_control = NEVER;
+    __pthread_mutex_unlock(&once_masterlock);
+    pthread_cond_broadcast(&once_finished);
+}
+
+int __pthread_once(pthread_once_t * once_control, void (*init_routine)(void))
+{
+  /* flag for doing the condition broadcast outside of mutex */
+  int state_changed;
+
+  /* Test without locking first for speed */
+  if (*once_control == DONE) {
+    READ_MEMORY_BARRIER();
+    return 0;
+  }
+  /* Lock and test again */
+
+  state_changed = 0;
+
+  __pthread_mutex_lock(&once_masterlock);
+
+  /* If this object was left in an IN_PROGRESS state in a parent
+     process (indicated by stale generation field), reset it to NEVER. */
+  if ((*once_control & 3) == IN_PROGRESS && (*once_control & ~3) != fork_generation)
+    *once_control = NEVER;
+
+  /* If init_routine is being called from another routine, wait until
+     it completes. */
+  while ((*once_control & 3) == IN_PROGRESS) {
+    pthread_cond_wait(&once_finished, &once_masterlock);
+  }
+  /* Here *once_control is stable and either NEVER or DONE. */
+  if (*once_control == NEVER) {
+    *once_control = IN_PROGRESS | fork_generation;
+    __pthread_mutex_unlock(&once_masterlock);
+    pthread_cleanup_push(pthread_once_cancelhandler, once_control);
+    init_routine();
+    pthread_cleanup_pop(0);
+    __pthread_mutex_lock(&once_masterlock);
+    WRITE_MEMORY_BARRIER();
+    *once_control = DONE;
+    state_changed = 1;
+  }
+  __pthread_mutex_unlock(&once_masterlock);
+
+  if (state_changed)
+    pthread_cond_broadcast(&once_finished);
+
+  return 0;
+}
+strong_alias (__pthread_once, pthread_once)
+
+/*
+ * Handle the state of the pthread_once mechanism across forks.  The
+ * once_masterlock is acquired in the parent process prior to a fork to ensure
+ * that no thread is in the critical region protected by the lock.  After the
+ * fork, the lock is released. In the child, the lock and the condition
+ * variable are simply reset.  The child also increments its generation
+ * counter which lets pthread_once calls detect stale IN_PROGRESS states
+ * and reset them back to NEVER.
+ */
+
+void __pthread_once_fork_prepare(void);
+void __pthread_once_fork_prepare(void)
+{
+  __pthread_mutex_lock(&once_masterlock);
+}
+
+void __pthread_once_fork_parent(void);
+void __pthread_once_fork_parent(void)
+{
+  __pthread_mutex_unlock(&once_masterlock);
+}
+
+void __pthread_once_fork_child(void);
+void __pthread_once_fork_child(void)
+{
+  __pthread_mutex_init(&once_masterlock, NULL);
+  pthread_cond_init(&once_finished, NULL);
+  if (fork_generation <= INT_MAX - 4)
+    fork_generation += 4;	/* leave least significant two bits zero */
+  else
+    fork_generation = 0;
+}

+ 21 - 0
libpthread/linuxthreads.old/pt-machine.c

@@ -0,0 +1,21 @@
+/* "Instantiation of machine-dependent pthreads inline functions.
+   Copyright (C) 1998 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   see <http://www.gnu.org/licenses/>.  */
+
+#define PT_EI
+
+#include <pt-machine.h>

+ 167 - 0
libpthread/linuxthreads.old/ptfork.c

@@ -0,0 +1,167 @@
+/* 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.                 */
+
+/* mods for uClibc: removed strong alias and defined funcs properly */
+
+/* The "atfork" stuff */
+
+#include <errno.h>
+
+#ifdef __ARCH_USE_MMU__
+
+#include <bits/uClibc_mutex.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "pthread.h"
+#include "internals.h"
+
+struct handler_list {
+  void (*handler)(void);
+  struct handler_list * next;
+};
+
+static pthread_mutex_t pthread_atfork_lock = PTHREAD_MUTEX_INITIALIZER;
+static struct handler_list * pthread_atfork_prepare = NULL;
+static struct handler_list * pthread_atfork_parent = NULL;
+static struct handler_list * pthread_atfork_child = NULL;
+
+#ifdef __MALLOC__
+__UCLIBC_MUTEX_EXTERN(__malloc_heap_lock);
+__UCLIBC_MUTEX_EXTERN(__malloc_sbrk_lock);
+#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__
+__UCLIBC_MUTEX_EXTERN(__malloc_mmb_heap_lock);
+#endif
+#elif defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__)
+__UCLIBC_MUTEX_EXTERN(__malloc_lock);
+#endif
+
+static void pthread_insert_list(struct handler_list ** list,
+                                void (*handler)(void),
+                                struct handler_list * newlist,
+                                int at_end)
+{
+  if (handler == NULL) return;
+  if (at_end) {
+    while(*list != NULL) list = &((*list)->next);
+  }
+  newlist->handler = handler;
+  newlist->next = *list;
+  *list = newlist;
+}
+
+struct handler_list_block {
+  struct handler_list prepare, parent, child;
+};
+
+int pthread_atfork(void (*prepare)(void),
+		     void (*parent)(void),
+		     void (*child)(void))
+{
+  struct handler_list_block * block =
+    (struct handler_list_block *) malloc(sizeof(struct handler_list_block));
+  if (block == NULL) return ENOMEM;
+  __pthread_mutex_lock(&pthread_atfork_lock);
+  /* "prepare" handlers are called in LIFO */
+  pthread_insert_list(&pthread_atfork_prepare, prepare, &block->prepare, 0);
+  /* "parent" handlers are called in FIFO */
+  pthread_insert_list(&pthread_atfork_parent, parent, &block->parent, 1);
+  /* "child" handlers are called in FIFO */
+  pthread_insert_list(&pthread_atfork_child, child, &block->child, 1);
+  __pthread_mutex_unlock(&pthread_atfork_lock);
+  return 0;
+}
+/*strong_alias (__pthread_atfork, pthread_atfork)*/
+
+static __inline__ void pthread_call_handlers(struct handler_list * list)
+{
+  for (/*nothing*/; list != NULL; list = list->next) (list->handler)();
+}
+
+void __pthread_once_fork_prepare(void);
+void __pthread_once_fork_child(void);
+void __pthread_once_fork_parent(void);
+
+static pid_t __fork(void)
+{
+  pid_t pid;
+  struct handler_list * prepare, * child, * parent;
+
+  __pthread_mutex_lock(&pthread_atfork_lock);
+  prepare = pthread_atfork_prepare;
+  child = pthread_atfork_child;
+  parent = pthread_atfork_parent;
+  pthread_call_handlers(prepare);
+
+  __pthread_once_fork_prepare();
+#ifdef __MALLOC__
+  __pthread_mutex_lock(&__malloc_sbrk_lock);
+  __pthread_mutex_lock(&__malloc_heap_lock);
+#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__
+  __pthread_mutex_lock(&__malloc_mmb_heap_lock);
+#endif
+#elif defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__)
+  __pthread_mutex_lock(&__malloc_lock);
+#endif
+
+  pid = __libc_fork();
+  if (pid == 0) {
+#if defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__)
+    __libc_lock_init_recursive(__malloc_lock);
+#elif defined(__MALLOC__)
+#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__
+    __libc_lock_init_adaptive(__malloc_mmb_heap_lock);
+#endif
+    __libc_lock_init_adaptive(__malloc_heap_lock);
+    __libc_lock_init(__malloc_sbrk_lock);
+#endif
+    __libc_lock_init_adaptive(pthread_atfork_lock);
+    __pthread_reset_main_thread();
+    __fresetlockfiles();
+    __pthread_once_fork_child();
+    pthread_call_handlers(child);
+  } else {
+#if defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__)
+    __pthread_mutex_unlock(&__malloc_lock);
+#elif defined(__MALLOC__)
+#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__
+    __pthread_mutex_unlock(&__malloc_mmb_heap_lock);
+#endif
+    __pthread_mutex_unlock(&__malloc_heap_lock);
+    __pthread_mutex_unlock(&__malloc_sbrk_lock);
+#endif
+    __pthread_mutex_unlock(&pthread_atfork_lock);
+    __pthread_once_fork_parent();
+    pthread_call_handlers(parent);
+  }
+  return pid;
+}
+strong_alias(__fork,fork)
+strong_alias(__fork,vfork)
+
+#else
+
+/* We can't support pthread_atfork without MMU, since we don't have
+   fork(), and we can't offer the correct semantics for vfork().  */
+int pthread_atfork(void (*prepare)(void),
+		   void (*parent)(void),
+		   void (*child)(void))
+{
+  /* ENOMEM is probably pushing it a little bit.
+     Take it as `no *virtual* memory' :-)  */
+  errno = ENOMEM;
+  return -1;
+}
+
+#endif

+ 1165 - 0
libpthread/linuxthreads.old/pthread.c

@@ -0,0 +1,1165 @@
+/* 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.                 */
+
+/* Thread creation, initialization, and basic low-level routines */
+
+#include <errno.h>
+#include <netdb.h>	/* for h_errno */
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <sys/resource.h>
+#include "pthread.h"
+#include "internals.h"
+#include "spinlock.h"
+#include "restart.h"
+#include "debug.h"      /* added to linuxthreads -StS */
+
+
+/* Mods for uClibc: Some includes */
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/syscall.h>
+
+libpthread_hidden_proto(waitpid)
+libpthread_hidden_proto(raise)
+
+/* These variables are used by the setup code.  */
+extern int _errno;
+extern int _h_errno;
+
+
+/* Descriptor of the initial thread */
+
+struct _pthread_descr_struct __pthread_initial_thread = {
+  &__pthread_initial_thread,  /* pthread_descr p_nextlive */
+  &__pthread_initial_thread,  /* pthread_descr p_prevlive */
+  NULL,                       /* pthread_descr p_nextwaiting */
+  NULL,			      /* pthread_descr p_nextlock */
+  PTHREAD_THREADS_MAX,        /* pthread_t p_tid */
+  0,                          /* int p_pid */
+  0,                          /* int p_priority */
+  &__pthread_handles[0].h_lock, /* struct _pthread_fastlock * p_lock */
+  0,                          /* int p_signal */
+  NULL,                       /* sigjmp_buf * p_signal_buf */
+  NULL,                       /* sigjmp_buf * p_cancel_buf */
+  0,                          /* char p_terminated */
+  0,                          /* char p_detached */
+  0,                          /* char p_exited */
+  NULL,                       /* void * p_retval */
+  0,                          /* int p_retval */
+  NULL,                       /* pthread_descr p_joining */
+  NULL,                       /* struct _pthread_cleanup_buffer * p_cleanup */
+  0,                          /* char p_cancelstate */
+  0,                          /* char p_canceltype */
+  0,                          /* char p_canceled */
+  &_errno,                       /* int *p_errnop */
+  0,                          /* int p_errno */
+  &_h_errno,                       /* int *p_h_errnop */
+  0,                          /* int p_h_errno */
+  NULL,                       /* char * p_in_sighandler */
+  0,                          /* char p_sigwaiting */
+  PTHREAD_START_ARGS_INITIALIZER, /* struct pthread_start_args p_start_args */
+  {NULL},                     /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */
+  {NULL},                     /* void * p_libc_specific[_LIBC_TSD_KEY_N] */
+  0,                          /* int p_userstack */
+  NULL,                       /* void * p_guardaddr */
+  0,                          /* size_t p_guardsize */
+  &__pthread_initial_thread,  /* pthread_descr p_self */
+  0,                          /* Always index 0 */
+  0,                          /* int p_report_events */
+  {{{0, }}, 0, NULL},         /* td_eventbuf_t p_eventbuf */
+  __ATOMIC_INITIALIZER,         /* struct pthread_atomic p_resume_count */
+  0,                          /* char p_woken_by_cancel */
+  0,                          /* char p_condvar_avail */
+  0,                          /* char p_sem_avail */
+  NULL,                       /* struct pthread_extricate_if *p_extricate */
+  NULL,	                      /* pthread_readlock_info *p_readlock_list; */
+  NULL,                       /* pthread_readlock_info *p_readlock_free; */
+  0                           /* int p_untracked_readlock_count; */
+#ifdef __UCLIBC_HAS_XLOCALE__
+  ,
+  &__global_locale_data,      /* __locale_t locale; */
+#endif /* __UCLIBC_HAS_XLOCALE__ */
+};
+
+/* Descriptor of the manager thread; none of this is used but the error
+   variables, the p_pid and p_priority fields,
+   and the address for identification.  */
+#define manager_thread (&__pthread_manager_thread)
+struct _pthread_descr_struct __pthread_manager_thread = {
+  NULL,                       /* pthread_descr p_nextlive */
+  NULL,                       /* pthread_descr p_prevlive */
+  NULL,                       /* pthread_descr p_nextwaiting */
+  NULL,			      /* pthread_descr p_nextlock */
+  0,                          /* int p_tid */
+  0,                          /* int p_pid */
+  0,                          /* int p_priority */
+  &__pthread_handles[1].h_lock, /* struct _pthread_fastlock * p_lock */
+  0,                          /* int p_signal */
+  NULL,                       /* sigjmp_buf * p_signal_buf */
+  NULL,                       /* sigjmp_buf * p_cancel_buf */
+  0,                          /* char p_terminated */
+  0,                          /* char p_detached */
+  0,                          /* char p_exited */
+  NULL,                       /* void * p_retval */
+  0,                          /* int p_retval */
+  NULL,                       /* pthread_descr p_joining */
+  NULL,                       /* struct _pthread_cleanup_buffer * p_cleanup */
+  0,                          /* char p_cancelstate */
+  0,                          /* char p_canceltype */
+  0,                          /* char p_canceled */
+  &__pthread_manager_thread.p_errno, /* int *p_errnop */
+  0,                          /* int p_errno */
+  NULL,                       /* int *p_h_errnop */
+  0,                          /* int p_h_errno */
+  NULL,                       /* char * p_in_sighandler */
+  0,                          /* char p_sigwaiting */
+  PTHREAD_START_ARGS_INITIALIZER, /* struct pthread_start_args p_start_args */
+  {NULL},                     /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */
+  {NULL},                     /* void * p_libc_specific[_LIBC_TSD_KEY_N] */
+  0,                          /* int p_userstack */
+  NULL,                       /* void * p_guardaddr */
+  0,                          /* size_t p_guardsize */
+  &__pthread_manager_thread,  /* pthread_descr p_self */
+  1,                          /* Always index 1 */
+  0,                          /* int p_report_events */
+  {{{0, }}, 0, NULL},         /* td_eventbuf_t p_eventbuf */
+  __ATOMIC_INITIALIZER,         /* struct pthread_atomic p_resume_count */
+  0,                          /* char p_woken_by_cancel */
+  0,                          /* char p_condvar_avail */
+  0,                          /* char p_sem_avail */
+  NULL,                       /* struct pthread_extricate_if *p_extricate */
+  NULL,	                      /* pthread_readlock_info *p_readlock_list; */
+  NULL,                       /* pthread_readlock_info *p_readlock_free; */
+  0                           /* int p_untracked_readlock_count; */
+#ifdef __UCLIBC_HAS_XLOCALE__
+  ,
+  &__global_locale_data,      /* __locale_t locale; */
+#endif /* __UCLIBC_HAS_XLOCALE__ */
+};
+
+/* Pointer to the main thread (the father of the thread manager thread) */
+/* Originally, this is the initial thread, but this changes after fork() */
+
+pthread_descr __pthread_main_thread = &__pthread_initial_thread;
+
+/* Limit between the stack of the initial thread (above) and the
+   stacks of other threads (below). Aligned on a STACK_SIZE boundary. */
+
+char *__pthread_initial_thread_bos = NULL;
+
+#ifndef __ARCH_USE_MMU__
+/* See nommu notes in internals.h and pthread_initialize() below. */
+char *__pthread_initial_thread_tos = NULL;
+char *__pthread_initial_thread_mid = NULL;
+#endif /* __ARCH_USE_MMU__ */
+
+/* File descriptor for sending requests to the thread manager. */
+/* Initially -1, meaning that the thread manager is not running. */
+
+int __pthread_manager_request = -1;
+
+/* Other end of the pipe for sending requests to the thread manager. */
+
+int __pthread_manager_reader;
+
+/* Limits of the thread manager stack */
+
+char *__pthread_manager_thread_bos = NULL;
+char *__pthread_manager_thread_tos = NULL;
+
+/* For process-wide exit() */
+
+int __pthread_exit_requested = 0;
+int __pthread_exit_code = 0;
+
+/* Communicate relevant LinuxThreads constants to gdb */
+
+const int __pthread_threads_max = PTHREAD_THREADS_MAX;
+const int __pthread_sizeof_handle = sizeof(struct pthread_handle_struct);
+const int __pthread_offsetof_descr = offsetof(struct pthread_handle_struct, h_descr);
+const int __pthread_offsetof_pid = offsetof(struct _pthread_descr_struct,
+                                            p_pid);
+const int __linuxthreads_pthread_sizeof_descr
+  = sizeof(struct _pthread_descr_struct);
+
+const int __linuxthreads_initial_report_events;
+
+const char __linuxthreads_version[] = VERSION;
+
+/* Forward declarations */
+static void pthread_onexit_process(int retcode, void *arg);
+static void pthread_handle_sigcancel(int sig);
+static void pthread_handle_sigrestart(int sig);
+static void pthread_handle_sigdebug(int sig);
+int __pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime);
+
+/* Signal numbers used for the communication.
+   In these variables we keep track of the used variables.  If the
+   platform does not support any real-time signals we will define the
+   values to some unreasonable value which will signal failing of all
+   the functions below.  */
+#ifndef __NR_rt_sigaction
+static int current_rtmin = -1;
+static int current_rtmax = -1;
+int __pthread_sig_restart = SIGUSR1;
+int __pthread_sig_cancel = SIGUSR2;
+int __pthread_sig_debug;
+#else
+
+#if __SIGRTMAX - __SIGRTMIN >= 3
+static int current_rtmin = __SIGRTMIN + 3;
+static int current_rtmax = __SIGRTMAX;
+int __pthread_sig_restart = __SIGRTMIN;
+int __pthread_sig_cancel = __SIGRTMIN + 1;
+int __pthread_sig_debug = __SIGRTMIN + 2;
+void (*__pthread_restart)(pthread_descr) = __pthread_restart_new;
+void (*__pthread_suspend)(pthread_descr) = __pthread_wait_for_restart_signal;
+int (*__pthread_timedsuspend)(pthread_descr, const struct timespec *) = __pthread_timedsuspend_new;
+#else
+static int current_rtmin = __SIGRTMIN;
+static int current_rtmax = __SIGRTMAX;
+int __pthread_sig_restart = SIGUSR1;
+int __pthread_sig_cancel = SIGUSR2;
+int __pthread_sig_debug;
+void (*__pthread_restart)(pthread_descr) = __pthread_restart_old;
+void (*__pthread_suspend)(pthread_descr) = __pthread_suspend_old;
+int (*__pthread_timedsuspend)(pthread_descr, const struct timespec *) = __pthread_timedsuspend_old;
+
+#endif
+
+/* Return number of available real-time signal with highest priority.  */
+int __libc_current_sigrtmin (void)
+{
+    return current_rtmin;
+}
+
+/* Return number of available real-time signal with lowest priority.  */
+int __libc_current_sigrtmax (void)
+{
+    return current_rtmax;
+}
+
+#if 0
+/* Allocate real-time signal with highest/lowest available
+   priority.  Please note that we don't use a lock since we assume
+   this function to be called at program start.  */
+int __libc_allocate_rtsig (int high);
+int __libc_allocate_rtsig (int high)
+{
+    if (current_rtmin == -1 || current_rtmin > current_rtmax)
+	/* We don't have anymore signal available.  */
+	return -1;
+    return high ? current_rtmin++ : current_rtmax--;
+}
+#endif
+#endif
+
+/* Initialize the pthread library.
+   Initialization is split in two functions:
+   - a constructor function that blocks the __pthread_sig_restart signal
+     (must do this very early, since the program could capture the signal
+      mask with e.g. sigsetjmp before creating the first thread);
+   - a regular function called from pthread_create when needed. */
+
+static void pthread_initialize(void) __attribute__((constructor));
+
+libpthread_hidden_proto(pthread_attr_destroy)
+libpthread_hidden_proto(pthread_attr_init)
+libpthread_hidden_proto(pthread_attr_getdetachstate)
+libpthread_hidden_proto(pthread_attr_setdetachstate)
+libpthread_hidden_proto(pthread_attr_getinheritsched)
+libpthread_hidden_proto(pthread_attr_setinheritsched)
+libpthread_hidden_proto(pthread_attr_setschedparam)
+libpthread_hidden_proto(pthread_attr_getschedparam)
+libpthread_hidden_proto(pthread_attr_getschedpolicy)
+libpthread_hidden_proto(pthread_attr_setschedpolicy)
+libpthread_hidden_proto(pthread_attr_getscope)
+libpthread_hidden_proto(pthread_attr_setscope)
+
+libpthread_hidden_proto(pthread_exit)
+
+libpthread_hidden_proto(pthread_equal)
+libpthread_hidden_proto(pthread_self)
+libpthread_hidden_proto(pthread_getschedparam)
+libpthread_hidden_proto(pthread_setschedparam)
+
+libpthread_hidden_proto(pthread_setcancelstate)
+libpthread_hidden_proto(pthread_setcanceltype)
+libpthread_hidden_proto(_pthread_cleanup_push_defer)
+libpthread_hidden_proto(_pthread_cleanup_pop_restore)
+
+libpthread_hidden_proto(pthread_cond_broadcast)
+libpthread_hidden_proto(pthread_cond_destroy)
+libpthread_hidden_proto(pthread_cond_init)
+libpthread_hidden_proto(pthread_cond_signal)
+libpthread_hidden_proto(pthread_cond_wait)
+libpthread_hidden_proto(pthread_cond_timedwait)
+
+libpthread_hidden_proto(pthread_condattr_destroy)
+libpthread_hidden_proto(pthread_condattr_init)
+
+struct pthread_functions __pthread_functions =
+  {
+#if !defined __UCLIBC_HAS_TLS__ && defined __UCLIBC_HAS_RPC__
+    .ptr_pthread_internal_tsd_set = __pthread_internal_tsd_set,
+    .ptr_pthread_internal_tsd_get = __pthread_internal_tsd_get,
+    .ptr_pthread_internal_tsd_address = __pthread_internal_tsd_address,
+#endif
+/*
+    .ptr_pthread_fork = __pthread_fork,
+*/
+    .ptr_pthread_attr_destroy = pthread_attr_destroy,
+    .ptr_pthread_attr_init = pthread_attr_init,
+    .ptr_pthread_attr_getdetachstate = pthread_attr_getdetachstate,
+    .ptr_pthread_attr_setdetachstate = pthread_attr_setdetachstate,
+    .ptr_pthread_attr_getinheritsched = pthread_attr_getinheritsched,
+    .ptr_pthread_attr_setinheritsched = pthread_attr_setinheritsched,
+    .ptr_pthread_attr_getschedparam = pthread_attr_getschedparam,
+    .ptr_pthread_attr_setschedparam = pthread_attr_setschedparam,
+    .ptr_pthread_attr_getschedpolicy = pthread_attr_getschedpolicy,
+    .ptr_pthread_attr_setschedpolicy = pthread_attr_setschedpolicy,
+    .ptr_pthread_attr_getscope = pthread_attr_getscope,
+    .ptr_pthread_attr_setscope = pthread_attr_setscope,
+    .ptr_pthread_condattr_destroy = pthread_condattr_destroy,
+    .ptr_pthread_condattr_init = pthread_condattr_init,
+    .ptr_pthread_cond_broadcast = pthread_cond_broadcast,
+    .ptr_pthread_cond_destroy = pthread_cond_destroy,
+    .ptr_pthread_cond_init = pthread_cond_init,
+    .ptr_pthread_cond_signal = pthread_cond_signal,
+    .ptr_pthread_cond_wait = pthread_cond_wait,
+    .ptr_pthread_cond_timedwait = pthread_cond_timedwait,
+    .ptr_pthread_equal = pthread_equal,
+    .ptr___pthread_exit = pthread_exit,
+    .ptr_pthread_getschedparam = pthread_getschedparam,
+    .ptr_pthread_setschedparam = pthread_setschedparam,
+    .ptr_pthread_mutex_destroy = __pthread_mutex_destroy,
+    .ptr_pthread_mutex_init = __pthread_mutex_init,
+    .ptr_pthread_mutex_lock = __pthread_mutex_lock,
+    .ptr_pthread_mutex_trylock = __pthread_mutex_trylock,
+    .ptr_pthread_mutex_unlock = __pthread_mutex_unlock,
+    .ptr_pthread_self = pthread_self,
+    .ptr_pthread_setcancelstate = pthread_setcancelstate,
+    .ptr_pthread_setcanceltype = pthread_setcanceltype,
+/*
+    .ptr_pthread_do_exit = pthread_do_exit,
+    .ptr_pthread_thread_self = pthread_thread_self,
+    .ptr_pthread_cleanup_upto = pthread_cleanup_upto,
+    .ptr_pthread_sigaction = pthread_sigaction,
+    .ptr_pthread_sigwait = pthread_sigwait,
+    .ptr_pthread_raise = pthread_raise,
+    .ptr__pthread_cleanup_push = _pthread_cleanup_push,
+    .ptr__pthread_cleanup_pop = _pthread_cleanup_pop,
+*/
+    .ptr__pthread_cleanup_push_defer = __pthread_cleanup_push_defer,
+    .ptr__pthread_cleanup_pop_restore = __pthread_cleanup_pop_restore
+  };
+#ifdef SHARED
+# define ptr_pthread_functions &__pthread_functions
+#else
+# define ptr_pthread_functions NULL
+#endif
+
+static int *__libc_multiple_threads_ptr;
+
+ /* Do some minimal initialization which has to be done during the
+    startup of the C library.  */
+void __pthread_initialize_minimal(void)
+{
+    /* If we have special thread_self processing, initialize
+     * that for the main thread now.  */
+#ifdef INIT_THREAD_SELF
+    INIT_THREAD_SELF(&__pthread_initial_thread, 0);
+#endif
+
+    __libc_multiple_threads_ptr = __libc_pthread_init (ptr_pthread_functions);
+}
+
+
+static void pthread_initialize(void)
+{
+  struct sigaction sa;
+  sigset_t mask;
+#ifdef __ARCH_USE_MMU__
+  struct rlimit limit;
+  rlim_t max_stack;
+#endif
+
+  /* If already done (e.g. by a constructor called earlier!), bail out */
+  if (__pthread_initial_thread_bos != NULL) return;
+#ifdef TEST_FOR_COMPARE_AND_SWAP
+  /* Test if compare-and-swap is available */
+  __pthread_has_cas = compare_and_swap_is_available();
+#endif
+  /* For the initial stack, reserve at least STACK_SIZE bytes of stack
+     below the current stack address, and align that on a
+     STACK_SIZE boundary. */
+  __pthread_initial_thread_bos =
+    (char *)(((long)CURRENT_STACK_FRAME - 2 * STACK_SIZE) & ~(STACK_SIZE - 1));
+  /* Update the descriptor for the initial thread. */
+  __pthread_initial_thread.p_pid = getpid();
+  /* If we have special thread_self processing, initialize that for the
+     main thread now.  */
+#ifdef INIT_THREAD_SELF
+  INIT_THREAD_SELF(&__pthread_initial_thread, 0);
+#endif
+  /* The errno/h_errno variable of the main thread are the global ones.  */
+  __pthread_initial_thread.p_errnop = &_errno;
+  __pthread_initial_thread.p_h_errnop = &_h_errno;
+
+#ifdef __UCLIBC_HAS_XLOCALE__
+  /* The locale of the main thread is the current locale in use. */
+  __pthread_initial_thread.locale = __curlocale_var;
+#endif /* __UCLIBC_HAS_XLOCALE__ */
+
+ {			   /* uClibc-specific stdio initialization for threads. */
+	 FILE *fp;
+
+	 _stdio_user_locking = 0;	/* 2 if threading not initialized */
+	 for (fp = _stdio_openlist; fp != NULL; fp = fp->__nextopen) {
+		 if (fp->__user_locking != 1) {
+			 fp->__user_locking = 0;
+		 }
+	 }
+ }
+
+  /* Play with the stack size limit to make sure that no stack ever grows
+     beyond STACK_SIZE minus two pages (one page for the thread descriptor
+     immediately beyond, and one page to act as a guard page). */
+
+#ifdef __ARCH_USE_MMU__
+  /* We cannot allocate a huge chunk of memory to mmap all thread stacks later
+   * on a non-MMU system. Thus, we don't need the rlimit either. -StS */
+  getrlimit(RLIMIT_STACK, &limit);
+  max_stack = STACK_SIZE - 2 * getpagesize();
+  if (limit.rlim_cur > max_stack) {
+    limit.rlim_cur = max_stack;
+    setrlimit(RLIMIT_STACK, &limit);
+  }
+#else
+  /* For non-MMU, the initial thread stack can reside anywhere in memory.
+   * We don't have a way of knowing where the kernel started things -- top
+   * or bottom (well, that isn't exactly true, but the solution is fairly
+   * complex and error prone).  All we can determine here is an address
+   * that lies within that stack.  Save that address as a reference so that
+   * as other thread stacks are created, we can adjust the estimated bounds
+   * of the initial thread's stack appropriately.
+   *
+   * This checking is handled in NOMMU_INITIAL_THREAD_BOUNDS(), so see that
+   * for a few more details.
+   */
+  __pthread_initial_thread_mid = CURRENT_STACK_FRAME;
+  __pthread_initial_thread_tos = (char *) -1;
+  __pthread_initial_thread_bos = (char *) 1; /* set it non-zero so we know we have been here */
+  PDEBUG("initial thread stack bounds: bos=%p, tos=%p\n",
+	 __pthread_initial_thread_bos, __pthread_initial_thread_tos);
+#endif /* __ARCH_USE_MMU__ */
+
+  /* Setup signal handlers for the initial thread.
+     Since signal handlers are shared between threads, these settings
+     will be inherited by all other threads. */
+  memset(&sa, 0, sizeof(sa));
+  sa.sa_handler = pthread_handle_sigrestart;
+  __libc_sigaction(__pthread_sig_restart, &sa, NULL);
+  sa.sa_handler = pthread_handle_sigcancel;
+  sigaddset(&sa.sa_mask, __pthread_sig_restart);
+  __libc_sigaction(__pthread_sig_cancel, &sa, NULL);
+  if (__pthread_sig_debug > 0) {
+      sa.sa_handler = pthread_handle_sigdebug;
+      __sigemptyset(&sa.sa_mask);
+      __libc_sigaction(__pthread_sig_debug, &sa, NULL);
+  }
+  /* Initially, block __pthread_sig_restart. Will be unblocked on demand. */
+  __sigemptyset(&mask);
+  sigaddset(&mask, __pthread_sig_restart);
+  sigprocmask(SIG_BLOCK, &mask, NULL);
+  /* And unblock __pthread_sig_cancel if it has been blocked. */
+  sigdelset(&mask, __pthread_sig_restart);
+  sigaddset(&mask, __pthread_sig_cancel);
+  sigprocmask(SIG_UNBLOCK, &mask, NULL);
+  /* Register an exit function to kill all other threads. */
+  /* Do it early so that user-registered atexit functions are called
+     before pthread_onexit_process. */
+  on_exit(pthread_onexit_process, NULL);
+}
+
+void __pthread_initialize(void);
+void __pthread_initialize(void)
+{
+  pthread_initialize();
+}
+
+int __pthread_initialize_manager(void)
+{
+  int manager_pipe[2];
+  int pid;
+  int report_events;
+  struct pthread_request request;
+
+  *__libc_multiple_threads_ptr = 1;
+
+  /* If basic initialization not done yet (e.g. we're called from a
+     constructor run before our constructor), do it now */
+  if (__pthread_initial_thread_bos == NULL) pthread_initialize();
+  /* Setup stack for thread manager */
+  __pthread_manager_thread_bos = malloc(THREAD_MANAGER_STACK_SIZE);
+  if (__pthread_manager_thread_bos == NULL) return -1;
+  __pthread_manager_thread_tos =
+    __pthread_manager_thread_bos + THREAD_MANAGER_STACK_SIZE;
+
+  /* On non-MMU systems we make sure that the initial thread bounds don't overlap
+   * with the manager stack frame */
+  NOMMU_INITIAL_THREAD_BOUNDS(__pthread_manager_thread_tos,__pthread_manager_thread_bos);
+  PDEBUG("manager stack: size=%ld, bos=%p, tos=%p\n", THREAD_MANAGER_STACK_SIZE,
+	 __pthread_manager_thread_bos, __pthread_manager_thread_tos);
+#if 0
+  PDEBUG("initial stack: estimate bos=%p, tos=%p\n",
+	 __pthread_initial_thread_bos, __pthread_initial_thread_tos);
+#endif
+
+  /* Setup pipe to communicate with thread manager */
+  if (pipe(manager_pipe) == -1) {
+    free(__pthread_manager_thread_bos);
+    return -1;
+  }
+  /* Start the thread manager */
+  pid = 0;
+#if defined(USE_TLS) && USE_TLS
+  if (__linuxthreads_initial_report_events != 0)
+    THREAD_SETMEM (((pthread_descr) NULL), p_report_events,
+		   __linuxthreads_initial_report_events);
+  report_events = THREAD_GETMEM (((pthread_descr) NULL), p_report_events);
+#else
+  if (__linuxthreads_initial_report_events != 0)
+    __pthread_initial_thread.p_report_events
+      = __linuxthreads_initial_report_events;
+  report_events = __pthread_initial_thread.p_report_events;
+#endif
+  if (__builtin_expect (report_events, 0))
+    {
+      /* It's a bit more complicated.  We have to report the creation of
+	 the manager thread.  */
+      int idx = __td_eventword (TD_CREATE);
+      uint32_t mask = __td_eventmask (TD_CREATE);
+
+      if ((mask & (__pthread_threads_events.event_bits[idx]
+		   | __pthread_initial_thread.p_eventbuf.eventmask.event_bits[idx]))
+	  != 0)
+	{
+
+	 __pthread_lock(__pthread_manager_thread.p_lock, NULL);
+
+#ifdef __ia64__
+	  pid = __clone2(__pthread_manager_event,
+			(void **) __pthread_manager_thread_tos,
+			THREAD_MANAGER_STACK_SIZE,
+			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
+			(void *)(long)manager_pipe[0]);
+#else
+	  pid = clone(__pthread_manager_event,
+			(void **) __pthread_manager_thread_tos,
+			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
+			(void *)(long)manager_pipe[0]);
+#endif
+
+	  if (pid != -1)
+	    {
+	      /* Now fill in the information about the new thread in
+	         the newly created thread's data structure.  We cannot let
+	         the new thread do this since we don't know whether it was
+	         already scheduled when we send the event.  */
+	      __pthread_manager_thread.p_eventbuf.eventdata =
+		  &__pthread_manager_thread;
+	      __pthread_manager_thread.p_eventbuf.eventnum = TD_CREATE;
+	      __pthread_last_event = &__pthread_manager_thread;
+	      __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1;
+	      __pthread_manager_thread.p_pid = pid;
+
+	      /* Now call the function which signals the event.  */
+	      __linuxthreads_create_event ();
+	    }
+	  /* Now restart the thread.  */
+	  __pthread_unlock(__pthread_manager_thread.p_lock);
+	}
+    }
+
+  if (pid == 0) {
+#ifdef __ia64__
+    pid = __clone2(__pthread_manager, (void **) __pthread_manager_thread_tos,
+		  THREAD_MANAGER_STACK_SIZE,
+		  CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
+		  (void *)(long)manager_pipe[0]);
+#else
+    pid = clone(__pthread_manager, (void **) __pthread_manager_thread_tos,
+		  CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
+		  (void *)(long)manager_pipe[0]);
+#endif
+  }
+  if (pid == -1) {
+    free(__pthread_manager_thread_bos);
+    close(manager_pipe[0]);
+    close(manager_pipe[1]);
+    return -1;
+  }
+  __pthread_manager_request = manager_pipe[1]; /* writing end */
+  __pthread_manager_reader = manager_pipe[0]; /* reading end */
+  __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1;
+  __pthread_manager_thread.p_pid = pid;
+
+  /* Make gdb aware of new thread manager */
+  if (__pthread_threads_debug && __pthread_sig_debug > 0)
+    {
+      raise(__pthread_sig_debug);
+      /* We suspend ourself and gdb will wake us up when it is
+	 ready to handle us. */
+      __pthread_wait_for_restart_signal(thread_self());
+    }
+  /* Synchronize debugging of the thread manager */
+  PDEBUG("send REQ_DEBUG to manager thread\n");
+  request.req_kind = REQ_DEBUG;
+  TEMP_FAILURE_RETRY(write(__pthread_manager_request,
+	      (char *) &request, sizeof(request)));
+  return 0;
+}
+
+/* Thread creation */
+
+int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
+			 void * (*start_routine)(void *), void *arg)
+{
+  pthread_descr self = thread_self();
+  struct pthread_request request;
+  if (__pthread_manager_request < 0) {
+    if (__pthread_initialize_manager() < 0) return EAGAIN;
+  }
+  request.req_thread = self;
+  request.req_kind = REQ_CREATE;
+  request.req_args.create.attr = attr;
+  request.req_args.create.fn = start_routine;
+  request.req_args.create.arg = arg;
+  sigprocmask(SIG_SETMASK, NULL, &request.req_args.create.mask);
+  PDEBUG("write REQ_CREATE to manager thread\n");
+  TEMP_FAILURE_RETRY(write(__pthread_manager_request,
+	      (char *) &request, sizeof(request)));
+  PDEBUG("before suspend(self)\n");
+  suspend(self);
+  PDEBUG("after suspend(self)\n");
+  if (THREAD_GETMEM(self, p_retcode) == 0)
+    *thread = (pthread_t) THREAD_GETMEM(self, p_retval);
+  return THREAD_GETMEM(self, p_retcode);
+}
+
+/* Simple operations on thread identifiers */
+
+pthread_t pthread_self(void)
+{
+  pthread_descr self = thread_self();
+  return THREAD_GETMEM(self, p_tid);
+}
+libpthread_hidden_def (pthread_self)
+
+int pthread_equal(pthread_t thread1, pthread_t thread2)
+{
+  return thread1 == thread2;
+}
+libpthread_hidden_def (pthread_equal)
+
+/* Helper function for thread_self in the case of user-provided stacks */
+
+#ifndef THREAD_SELF
+
+pthread_descr __pthread_find_self(void)
+{
+  char * sp = CURRENT_STACK_FRAME;
+  pthread_handle h;
+
+  /* __pthread_handles[0] is the initial thread, __pthread_handles[1] is
+     the manager threads handled specially in thread_self(), so start at 2 */
+  h = __pthread_handles + 2;
+  while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom)) h++;
+
+#ifdef DEBUG_PT
+  if (h->h_descr == NULL) {
+      printf("*** %s ERROR descriptor is NULL!!!!! ***\n\n", __FUNCTION__);
+      _exit(1);
+  }
+#endif
+
+  return h->h_descr;
+}
+#else
+
+static pthread_descr thread_self_stack(void)
+{
+    char *sp = CURRENT_STACK_FRAME;
+    pthread_handle h;
+
+    if (sp >= __pthread_manager_thread_bos && sp < __pthread_manager_thread_tos)
+	return manager_thread;
+    h = __pthread_handles + 2;
+# if defined(USE_TLS) && USE_TLS
+    while (h->h_descr == NULL
+	    || ! (sp <= (char *) h->h_descr->p_stackaddr && sp >= h->h_bottom))
+	h++;
+# else
+    while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom))
+	h++;
+# endif
+    return h->h_descr;
+}
+
+#endif
+
+/* Thread scheduling */
+
+int pthread_setschedparam(pthread_t thread, int policy,
+                          const struct sched_param *param)
+{
+  pthread_handle handle = thread_handle(thread);
+  pthread_descr th;
+
+  __pthread_lock(&handle->h_lock, NULL);
+  if (invalid_handle(handle, thread)) {
+    __pthread_unlock(&handle->h_lock);
+    return ESRCH;
+  }
+  th = handle->h_descr;
+  if (sched_setscheduler(th->p_pid, policy, param) == -1) {
+    __pthread_unlock(&handle->h_lock);
+    return errno;
+  }
+  th->p_priority = policy == SCHED_OTHER ? 0 : param->sched_priority;
+  __pthread_unlock(&handle->h_lock);
+  if (__pthread_manager_request >= 0)
+    __pthread_manager_adjust_prio(th->p_priority);
+  return 0;
+}
+libpthread_hidden_def(pthread_setschedparam)
+
+int pthread_getschedparam(pthread_t thread, int *policy,
+                          struct sched_param *param)
+{
+  pthread_handle handle = thread_handle(thread);
+  int pid, pol;
+
+  __pthread_lock(&handle->h_lock, NULL);
+  if (invalid_handle(handle, thread)) {
+    __pthread_unlock(&handle->h_lock);
+    return ESRCH;
+  }
+  pid = handle->h_descr->p_pid;
+  __pthread_unlock(&handle->h_lock);
+  pol = sched_getscheduler(pid);
+  if (pol == -1) return errno;
+  if (sched_getparam(pid, param) == -1) return errno;
+  *policy = pol;
+  return 0;
+}
+libpthread_hidden_def(pthread_getschedparam)
+
+/* Process-wide exit() request */
+
+static void pthread_onexit_process(int retcode, void *arg attribute_unused)
+{
+    struct pthread_request request;
+    pthread_descr self = thread_self();
+
+    if (__pthread_manager_request >= 0) {
+	request.req_thread = self;
+	request.req_kind = REQ_PROCESS_EXIT;
+	request.req_args.exit.code = retcode;
+	TEMP_FAILURE_RETRY(write(__pthread_manager_request,
+		    (char *) &request, sizeof(request)));
+	suspend(self);
+	/* Main thread should accumulate times for thread manager and its
+	   children, so that timings for main thread account for all threads. */
+	if (self == __pthread_main_thread) {
+	    waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE);
+	    /* Since all threads have been asynchronously terminated
+	     * (possibly holding locks), free cannot be used any more.  */
+	    __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL;
+	}
+    }
+}
+
+/* The handler for the RESTART signal just records the signal received
+   in the thread descriptor, and optionally performs a siglongjmp
+   (for pthread_cond_timedwait). */
+
+static void pthread_handle_sigrestart(int sig)
+{
+    pthread_descr self = thread_self();
+    THREAD_SETMEM(self, p_signal, sig);
+    if (THREAD_GETMEM(self, p_signal_jmp) != NULL)
+	siglongjmp(*THREAD_GETMEM(self, p_signal_jmp), 1);
+}
+
+/* The handler for the CANCEL signal checks for cancellation
+   (in asynchronous mode), for process-wide exit and exec requests.
+   For the thread manager thread, redirect the signal to
+   __pthread_manager_sighandler. */
+
+static void pthread_handle_sigcancel(int sig)
+{
+  pthread_descr self = thread_self();
+  sigjmp_buf * jmpbuf;
+
+
+  if (self == &__pthread_manager_thread)
+    {
+#ifdef THREAD_SELF
+      /* A new thread might get a cancel signal before it is fully
+	 initialized, so that the thread register might still point to the
+	 manager thread.  Double check that this is really the manager
+	 thread.  */
+      pthread_descr real_self = thread_self_stack();
+      if (real_self == &__pthread_manager_thread)
+	{
+	  __pthread_manager_sighandler(sig);
+	  return;
+	}
+      /* Oops, thread_self() isn't working yet..  */
+      self = real_self;
+# ifdef INIT_THREAD_SELF
+      INIT_THREAD_SELF(self, self->p_nr);
+# endif
+#else
+      __pthread_manager_sighandler(sig);
+      return;
+#endif
+    }
+  if (__builtin_expect (__pthread_exit_requested, 0)) {
+    /* Main thread should accumulate times for thread manager and its
+       children, so that timings for main thread account for all threads. */
+    if (self == __pthread_main_thread) {
+#if defined(USE_TLS) && USE_TLS
+      waitpid(__pthread_manager_thread->p_pid, NULL, __WCLONE);
+#else
+      waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE);
+#endif
+    }
+    _exit(__pthread_exit_code);
+  }
+  if (__builtin_expect (THREAD_GETMEM(self, p_canceled), 0)
+      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
+    if (THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)
+      __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+    jmpbuf = THREAD_GETMEM(self, p_cancel_jmp);
+    if (jmpbuf != NULL) {
+      THREAD_SETMEM(self, p_cancel_jmp, NULL);
+      siglongjmp(*jmpbuf, 1);
+    }
+  }
+}
+
+/* Handler for the DEBUG signal.
+   The debugging strategy is as follows:
+   On reception of a REQ_DEBUG request (sent by new threads created to
+   the thread manager under debugging mode), the thread manager throws
+   __pthread_sig_debug to itself. The debugger (if active) intercepts
+   this signal, takes into account new threads and continue execution
+   of the thread manager by propagating the signal because it doesn't
+   know what it is specifically done for. In the current implementation,
+   the thread manager simply discards it. */
+
+static void pthread_handle_sigdebug(int sig attribute_unused)
+{
+  /* Nothing */
+}
+
+/* Reset the state of the thread machinery after a fork().
+   Close the pipe used for requests and set the main thread to the forked
+   thread.
+   Notice that we can't free the stack segments, as the forked thread
+   may hold pointers into them. */
+
+void __pthread_reset_main_thread(void)
+{
+  pthread_descr self = thread_self();
+
+  if (__pthread_manager_request != -1) {
+    /* Free the thread manager stack */
+    free(__pthread_manager_thread_bos);
+    __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL;
+    /* Close the two ends of the pipe */
+    close(__pthread_manager_request);
+    close(__pthread_manager_reader);
+    __pthread_manager_request = __pthread_manager_reader = -1;
+  }
+
+  /* Update the pid of the main thread */
+  THREAD_SETMEM(self, p_pid, getpid());
+  /* Make the forked thread the main thread */
+  __pthread_main_thread = self;
+  THREAD_SETMEM(self, p_nextlive, self);
+  THREAD_SETMEM(self, p_prevlive, self);
+  /* Now this thread modifies the global variables.  */
+  THREAD_SETMEM(self, p_errnop, &_errno);
+  THREAD_SETMEM(self, p_h_errnop, &_h_errno);
+}
+
+/* Process-wide exec() request */
+
+void __pthread_kill_other_threads_np(void)
+{
+  struct sigaction sa;
+  /* Terminate all other threads and thread manager */
+  pthread_onexit_process(0, NULL);
+  /* Make current thread the main thread in case the calling thread
+     changes its mind, does not exec(), and creates new threads instead. */
+  __pthread_reset_main_thread();
+  /* Reset the signal handlers behaviour for the signals the
+     implementation uses since this would be passed to the new
+     process.  */
+  memset(&sa, 0, sizeof(sa));
+  if (SIG_DFL) /* if it's constant zero, it's already done */
+    sa.sa_handler = SIG_DFL;
+  __libc_sigaction(__pthread_sig_restart, &sa, NULL);
+  __libc_sigaction(__pthread_sig_cancel, &sa, NULL);
+  if (__pthread_sig_debug > 0)
+    __libc_sigaction(__pthread_sig_debug, &sa, NULL);
+}
+weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
+
+/* Concurrency symbol level.  */
+static int current_level;
+
+int __pthread_setconcurrency(int level)
+{
+  /* We don't do anything unless we have found a useful interpretation.  */
+  current_level = level;
+  return 0;
+}
+weak_alias (__pthread_setconcurrency, pthread_setconcurrency)
+
+int __pthread_getconcurrency(void)
+{
+  return current_level;
+}
+weak_alias (__pthread_getconcurrency, pthread_getconcurrency)
+
+
+/* Primitives for controlling thread execution */
+
+void __pthread_wait_for_restart_signal(pthread_descr self)
+{
+    sigset_t mask;
+
+    sigprocmask(SIG_SETMASK, NULL, &mask); /* Get current signal mask */
+    sigdelset(&mask, __pthread_sig_restart); /* Unblock the restart signal */
+    THREAD_SETMEM(self, p_signal, 0);
+    do {
+	sigsuspend(&mask);                   /* Wait for signal */
+    } while (THREAD_GETMEM(self, p_signal) !=__pthread_sig_restart);
+
+    READ_MEMORY_BARRIER(); /* See comment in __pthread_restart_new */
+}
+
+#ifndef __NR_rt_sigaction
+/* The _old variants are for 2.0 and early 2.1 kernels which don't have RT
+   signals.
+   On these kernels, we use SIGUSR1 and SIGUSR2 for restart and cancellation.
+   Since the restart signal does not queue, we use an atomic counter to create
+   queuing semantics. This is needed to resolve a rare race condition in
+   pthread_cond_timedwait_relative. */
+
+void __pthread_restart_old(pthread_descr th)
+{
+    if (atomic_increment(&th->p_resume_count) == -1)
+	kill(th->p_pid, __pthread_sig_restart);
+}
+
+void __pthread_suspend_old(pthread_descr self)
+{
+    if (atomic_decrement(&self->p_resume_count) <= 0)
+	__pthread_wait_for_restart_signal(self);
+}
+
+int
+__pthread_timedsuspend_old(pthread_descr self, const struct timespec *abstime)
+{
+  sigset_t unblock, initial_mask;
+  int was_signalled = 0;
+  sigjmp_buf jmpbuf;
+
+  if (atomic_decrement(&self->p_resume_count) == 0) {
+    /* Set up a longjmp handler for the restart signal, unblock
+       the signal and sleep. */
+
+    if (sigsetjmp(jmpbuf, 1) == 0) {
+      THREAD_SETMEM(self, p_signal_jmp, &jmpbuf);
+      THREAD_SETMEM(self, p_signal, 0);
+      /* Unblock the restart signal */
+      __sigemptyset(&unblock);
+      sigaddset(&unblock, __pthread_sig_restart);
+      sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask);
+
+      while (1) {
+	struct timeval now;
+	struct timespec reltime;
+
+	/* Compute a time offset relative to now.  */
+	gettimeofday (&now, NULL);
+	reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000;
+	reltime.tv_sec = abstime->tv_sec - now.tv_sec;
+	if (reltime.tv_nsec < 0) {
+	  reltime.tv_nsec += 1000000000;
+	  reltime.tv_sec -= 1;
+	}
+
+	/* Sleep for the required duration. If woken by a signal,
+	   resume waiting as required by Single Unix Specification.  */
+	if (reltime.tv_sec < 0 || nanosleep(&reltime, NULL) == 0)
+	  break;
+      }
+
+      /* Block the restart signal again */
+      sigprocmask(SIG_SETMASK, &initial_mask, NULL);
+      was_signalled = 0;
+    } else {
+      was_signalled = 1;
+    }
+    THREAD_SETMEM(self, p_signal_jmp, NULL);
+  }
+
+  /* Now was_signalled is true if we exited the above code
+     due to the delivery of a restart signal.  In that case,
+     we know we have been dequeued and resumed and that the
+     resume count is balanced.  Otherwise, there are some
+     cases to consider. First, try to bump up the resume count
+     back to zero. If it goes to 1, it means restart() was
+     invoked on this thread. The signal must be consumed
+     and the count bumped down and everything is cool. We
+     can return a 1 to the caller.
+     Otherwise, no restart was delivered yet, so a potential
+     race exists; we return a 0 to the caller which must deal
+     with this race in an appropriate way; for example by
+     atomically removing the thread from consideration for a
+     wakeup---if such a thing fails, it means a restart is
+     being delivered. */
+
+  if (!was_signalled) {
+    if (atomic_increment(&self->p_resume_count) != -1) {
+      __pthread_wait_for_restart_signal(self);
+      atomic_decrement(&self->p_resume_count); /* should be zero now! */
+      /* woke spontaneously and consumed restart signal */
+      return 1;
+    }
+    /* woke spontaneously but did not consume restart---caller must resolve */
+    return 0;
+  }
+  /* woken due to restart signal */
+  return 1;
+}
+#endif /* __NR_rt_sigaction */
+
+
+#ifdef __NR_rt_sigaction
+void __pthread_restart_new(pthread_descr th)
+{
+    /* The barrier is proabably not needed, in which case it still documents
+       our assumptions. The intent is to commit previous writes to shared
+       memory so the woken thread will have a consistent view.  Complementary
+       read barriers are present to the suspend functions. */
+    WRITE_MEMORY_BARRIER();
+    kill(th->p_pid, __pthread_sig_restart);
+}
+
+int __pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime)
+{
+    sigset_t unblock, initial_mask;
+    int was_signalled = 0;
+    sigjmp_buf jmpbuf;
+
+    if (sigsetjmp(jmpbuf, 1) == 0) {
+	THREAD_SETMEM(self, p_signal_jmp, &jmpbuf);
+	THREAD_SETMEM(self, p_signal, 0);
+	/* Unblock the restart signal */
+	__sigemptyset(&unblock);
+	sigaddset(&unblock, __pthread_sig_restart);
+	sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask);
+
+	while (1) {
+	    struct timeval now;
+	    struct timespec reltime;
+
+	    /* Compute a time offset relative to now.  */
+	    gettimeofday (&now, NULL);
+	    reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000;
+	    reltime.tv_sec = abstime->tv_sec - now.tv_sec;
+	    if (reltime.tv_nsec < 0) {
+		reltime.tv_nsec += 1000000000;
+		reltime.tv_sec -= 1;
+	    }
+
+	    /* Sleep for the required duration. If woken by a signal,
+	       resume waiting as required by Single Unix Specification.  */
+	    if (reltime.tv_sec < 0 || nanosleep(&reltime, NULL) == 0)
+		break;
+	}
+
+	/* Block the restart signal again */
+	sigprocmask(SIG_SETMASK, &initial_mask, NULL);
+	was_signalled = 0;
+    } else {
+	was_signalled = 1;
+    }
+    THREAD_SETMEM(self, p_signal_jmp, NULL);
+
+    /* Now was_signalled is true if we exited the above code
+       due to the delivery of a restart signal.  In that case,
+       everything is cool. We have been removed from whatever
+       we were waiting on by the other thread, and consumed its signal.
+
+       Otherwise we this thread woke up spontaneously, or due to a signal other
+       than restart. This is an ambiguous case  that must be resolved by
+       the caller; the thread is still eligible for a restart wakeup
+       so there is a race. */
+
+    READ_MEMORY_BARRIER(); /* See comment in __pthread_restart_new */
+    return was_signalled;
+}
+#endif
+
+/* Debugging aid */
+
+#ifdef DEBUG_PT
+#include <stdarg.h>
+
+void __pthread_message(char * fmt, ...)
+{
+  char buffer[1024];
+  va_list args;
+  sprintf(buffer, "%05d : ", getpid());
+  va_start(args, fmt);
+  vsnprintf(buffer + 8, sizeof(buffer) - 8, fmt, args);
+  va_end(args);
+  TEMP_FAILURE_RETRY(write(2, buffer, strlen(buffer)));
+}
+
+#endif
+
+
+#ifndef __PIC__
+/* We need a hook to force the cancellation wrappers to be linked in when
+   static libpthread is used.  */
+extern const char __pthread_provide_wrappers;
+static const char *const __pthread_require_wrappers =
+  &__pthread_provide_wrappers;
+#endif

+ 0 - 0
libpthread/linuxthreads/ptlongjmp.c → libpthread/linuxthreads.old/ptlongjmp.c


+ 60 - 0
libpthread/linuxthreads.old/queue.h

@@ -0,0 +1,60 @@
+/* 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.                 */
+
+/* Waiting queues */
+
+/* Waiting queues are represented by lists of thread descriptors
+   linked through their p_nextwaiting field.  The lists are kept
+   sorted by decreasing priority, and then decreasing waiting time. */
+
+static __inline__ void enqueue(pthread_descr * q, pthread_descr th)
+{
+  int prio = th->p_priority;
+  for (; *q != NULL; q = &((*q)->p_nextwaiting)) {
+    if (prio > (*q)->p_priority) {
+      th->p_nextwaiting = *q;
+      *q = th;
+      return;
+    }
+  }
+  *q = th;
+}
+
+static __inline__ pthread_descr dequeue(pthread_descr * q)
+{
+  pthread_descr th;
+  th = *q;
+  if (th != NULL) {
+    *q = th->p_nextwaiting;
+    th->p_nextwaiting = NULL;
+  }
+  return th;
+}
+
+static __inline__ int remove_from_queue(pthread_descr * q, pthread_descr th)
+{
+  for (; *q != NULL; q = &((*q)->p_nextwaiting)) {
+    if (*q == th) {
+      *q = th->p_nextwaiting;
+      th->p_nextwaiting = NULL;
+      return 1;
+    }
+  }
+  return 0;
+}
+
+static __inline__ int queue_is_empty(pthread_descr * q)
+{
+    return *q == NULL;
+}

+ 50 - 0
libpthread/linuxthreads.old/restart.h

@@ -0,0 +1,50 @@
+/* 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.                 */
+
+#include <signal.h>
+#include <sys/syscall.h>
+#define __ASSUME_REALTIME_SIGNALS defined(__NR_rt_sigaction)
+
+/* Primitives for controlling thread execution */
+
+static __inline__ void restart(pthread_descr th)
+{
+  /* See pthread.c */
+#if __ASSUME_REALTIME_SIGNALS
+  __pthread_restart_new(th);
+#else
+  __pthread_restart(th);
+#endif
+}
+
+static __inline__ void suspend(pthread_descr self)
+{
+  /* See pthread.c */
+#if __ASSUME_REALTIME_SIGNALS
+  __pthread_wait_for_restart_signal(self);
+#else
+  __pthread_suspend(self);
+#endif
+}
+
+static __inline__ int timedsuspend(pthread_descr self,
+		const struct timespec *abstime)
+{
+  /* See pthread.c */
+#if __ASSUME_REALTIME_SIGNALS
+  return __pthread_timedsuspend_new(self, abstime);
+#else
+  return __pthread_timedsuspend(self, abstime);
+#endif
+}

+ 485 - 0
libpthread/linuxthreads.old/rwlock.c

@@ -0,0 +1,485 @@
+/* Read-write lock implementation.
+   Copyright (C) 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Xavier Leroy <Xavier.Leroy@inria.fr>
+   and Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+   The GNU C Library 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.
+
+   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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   see <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include "internals.h"
+#include "queue.h"
+#include "spinlock.h"
+#include "restart.h"
+
+/*
+ * Check whether the calling thread already owns one or more read locks on the
+ * specified lock. If so, return a pointer to the read lock info structure
+ * corresponding to that lock.
+ */
+
+static pthread_readlock_info *
+rwlock_is_in_list(pthread_descr self, pthread_rwlock_t *rwlock)
+{
+  pthread_readlock_info *info;
+
+  for (info = self->p_readlock_list; info != NULL; info = info->pr_next)
+    {
+      if (info->pr_lock == rwlock)
+	return info;
+    }
+
+  return NULL;
+}
+
+/*
+ * Add a new lock to the thread's list of locks for which it has a read lock.
+ * A new info node must be allocated for this, which is taken from the thread's
+ * free list, or by calling malloc. If malloc fails, a null pointer is
+ * returned. Otherwise the lock info structure is initialized and pushed
+ * onto the thread's list.
+ */
+
+static pthread_readlock_info *
+rwlock_add_to_list(pthread_descr self, pthread_rwlock_t *rwlock)
+{
+  pthread_readlock_info *info = self->p_readlock_free;
+
+  if (info != NULL)
+    self->p_readlock_free = info->pr_next;
+  else
+    info = malloc(sizeof *info);
+
+  if (info == NULL)
+    return NULL;
+
+  info->pr_lock_count = 1;
+  info->pr_lock = rwlock;
+  info->pr_next = self->p_readlock_list;
+  self->p_readlock_list = info;
+
+  return info;
+}
+
+/*
+ * If the thread owns a read lock over the given pthread_rwlock_t,
+ * and this read lock is tracked in the thread's lock list,
+ * this function returns a pointer to the info node in that list.
+ * It also decrements the lock count within that node, and if
+ * it reaches zero, it removes the node from the list.
+ * If nothing is found, it returns a null pointer.
+ */
+
+static pthread_readlock_info *
+rwlock_remove_from_list(pthread_descr self, pthread_rwlock_t *rwlock)
+{
+  pthread_readlock_info **pinfo;
+
+  for (pinfo = &self->p_readlock_list; *pinfo != NULL; pinfo = &(*pinfo)->pr_next)
+    {
+      if ((*pinfo)->pr_lock == rwlock)
+	{
+	  pthread_readlock_info *info = *pinfo;
+	  if (--info->pr_lock_count == 0)
+	    *pinfo = info->pr_next;
+	  return info;
+	}
+    }
+
+  return NULL;
+}
+
+/*
+ * This function checks whether the conditions are right to place a read lock.
+ * It returns 1 if so, otherwise zero. The rwlock's internal lock must be
+ * locked upon entry.
+ */
+
+static int
+rwlock_can_rdlock(pthread_rwlock_t *rwlock, int have_lock_already)
+{
+  /* Can't readlock; it is write locked. */
+  if (rwlock->__rw_writer != NULL)
+    return 0;
+
+  /* Lock prefers readers; get it. */
+  if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP)
+    return 1;
+
+  /* Lock prefers writers, but none are waiting. */
+  if (queue_is_empty(&rwlock->__rw_write_waiting))
+    return 1;
+
+  /* Writers are waiting, but this thread already has a read lock */
+  if (have_lock_already)
+    return 1;
+
+  /* Writers are waiting, and this is a new lock */
+  return 0;
+}
+
+/*
+ * This function helps support brain-damaged recursive read locking
+ * semantics required by Unix 98, while maintaining write priority.
+ * This basically determines whether this thread already holds a read lock
+ * already. It returns 1 if so, otherwise it returns 0.
+ *
+ * If the thread has any ``untracked read locks'' then it just assumes
+ * that this lock is among them, just to be safe, and returns 1.
+ *
+ * Also, if it finds the thread's lock in the list, it sets the pointer
+ * referenced by pexisting to refer to the list entry.
+ *
+ * If the thread has no untracked locks, and the lock is not found
+ * in its list, then it is added to the list. If this fails,
+ * then *pout_of_mem is set to 1.
+ */
+
+static int
+rwlock_have_already(pthread_descr *pself, pthread_rwlock_t *rwlock,
+    pthread_readlock_info **pexisting, int *pout_of_mem)
+{
+  pthread_readlock_info *existing = NULL;
+  int out_of_mem = 0, have_lock_already = 0;
+  pthread_descr self = *pself;
+
+  if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_WRITER_NP)
+    {
+      if (!self)
+	self = thread_self();
+
+      existing = rwlock_is_in_list(self, rwlock);
+
+      if (existing != NULL || self->p_untracked_readlock_count > 0)
+	have_lock_already = 1;
+      else
+	{
+	  existing = rwlock_add_to_list(self, rwlock);
+	  if (existing == NULL)
+	    out_of_mem = 1;
+	}
+    }
+
+  *pout_of_mem = out_of_mem;
+  *pexisting = existing;
+  *pself = self;
+
+  return have_lock_already;
+}
+
+int
+pthread_rwlock_init (pthread_rwlock_t *rwlock,
+		     const pthread_rwlockattr_t *attr)
+{
+  __pthread_init_lock(&rwlock->__rw_lock);
+  rwlock->__rw_readers = 0;
+  rwlock->__rw_writer = NULL;
+  rwlock->__rw_read_waiting = NULL;
+  rwlock->__rw_write_waiting = NULL;
+
+  if (attr == NULL)
+    {
+      rwlock->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP;
+      rwlock->__rw_pshared = PTHREAD_PROCESS_PRIVATE;
+    }
+  else
+    {
+      rwlock->__rw_kind = attr->__lockkind;
+      rwlock->__rw_pshared = attr->__pshared;
+    }
+
+  return 0;
+}
+
+
+int
+pthread_rwlock_destroy (pthread_rwlock_t *rwlock)
+{
+  int readers;
+  _pthread_descr writer;
+
+  __pthread_lock (&rwlock->__rw_lock, NULL);
+  readers = rwlock->__rw_readers;
+  writer = rwlock->__rw_writer;
+  __pthread_unlock (&rwlock->__rw_lock);
+
+  if (readers > 0 || writer != NULL)
+    return EBUSY;
+
+  return 0;
+}
+
+int
+pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
+{
+  pthread_descr self = NULL;
+  pthread_readlock_info *existing;
+  int out_of_mem, have_lock_already;
+
+  have_lock_already = rwlock_have_already(&self, rwlock,
+      &existing, &out_of_mem);
+
+  for (;;)
+    {
+      if (self == NULL)
+	self = thread_self ();
+
+      __pthread_lock (&rwlock->__rw_lock, self);
+
+      if (rwlock_can_rdlock(rwlock, have_lock_already))
+	break;
+
+      enqueue (&rwlock->__rw_read_waiting, self);
+      __pthread_unlock (&rwlock->__rw_lock);
+      suspend (self); /* This is not a cancellation point */
+    }
+
+  ++rwlock->__rw_readers;
+  __pthread_unlock (&rwlock->__rw_lock);
+
+  if (have_lock_already || out_of_mem)
+    {
+      if (existing != NULL)
+	existing->pr_lock_count++;
+      else
+	self->p_untracked_readlock_count++;
+    }
+
+  return 0;
+}
+
+int
+pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock)
+{
+  pthread_descr self = thread_self();
+  pthread_readlock_info *existing;
+  int out_of_mem, have_lock_already;
+  int retval = EBUSY;
+
+  have_lock_already = rwlock_have_already(&self, rwlock,
+      &existing, &out_of_mem);
+
+  __pthread_lock (&rwlock->__rw_lock, self);
+
+  /* 0 is passed to here instead of have_lock_already.
+     This is to meet Single Unix Spec requirements:
+     if writers are waiting, pthread_rwlock_tryrdlock
+     does not acquire a read lock, even if the caller has
+     one or more read locks already. */
+
+  if (rwlock_can_rdlock(rwlock, 0))
+    {
+      ++rwlock->__rw_readers;
+      retval = 0;
+    }
+
+  __pthread_unlock (&rwlock->__rw_lock);
+
+  if (retval == 0)
+    {
+      if (have_lock_already || out_of_mem)
+	{
+	  if (existing != NULL)
+	    existing->pr_lock_count++;
+	  else
+	    self->p_untracked_readlock_count++;
+	}
+    }
+
+  return retval;
+}
+
+
+int
+pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
+{
+  pthread_descr self = thread_self ();
+
+  while(1)
+    {
+      __pthread_lock (&rwlock->__rw_lock, self);
+      if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL)
+	{
+	  rwlock->__rw_writer = self;
+	  __pthread_unlock (&rwlock->__rw_lock);
+	  return 0;
+	}
+
+      /* Suspend ourselves, then try again */
+      enqueue (&rwlock->__rw_write_waiting, self);
+      __pthread_unlock (&rwlock->__rw_lock);
+      suspend (self); /* This is not a cancellation point */
+    }
+}
+
+
+int
+pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock)
+{
+  int result = EBUSY;
+
+  __pthread_lock (&rwlock->__rw_lock, NULL);
+  if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL)
+    {
+      rwlock->__rw_writer = thread_self ();
+      result = 0;
+    }
+  __pthread_unlock (&rwlock->__rw_lock);
+
+  return result;
+}
+
+
+int
+pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
+{
+  pthread_descr torestart;
+  pthread_descr th;
+
+  __pthread_lock (&rwlock->__rw_lock, NULL);
+  if (rwlock->__rw_writer != NULL)
+    {
+      /* Unlocking a write lock.  */
+      if (rwlock->__rw_writer != thread_self ())
+	{
+	  __pthread_unlock (&rwlock->__rw_lock);
+	  return EPERM;
+	}
+      rwlock->__rw_writer = NULL;
+
+      if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP
+	  || (th = dequeue (&rwlock->__rw_write_waiting)) == NULL)
+	{
+	  /* Restart all waiting readers.  */
+	  torestart = rwlock->__rw_read_waiting;
+	  rwlock->__rw_read_waiting = NULL;
+	  __pthread_unlock (&rwlock->__rw_lock);
+	  while ((th = dequeue (&torestart)) != NULL)
+	    restart (th);
+	}
+      else
+	{
+	  /* Restart one waiting writer.  */
+	  __pthread_unlock (&rwlock->__rw_lock);
+	  restart (th);
+	}
+    }
+  else
+    {
+      /* Unlocking a read lock.  */
+      if (rwlock->__rw_readers == 0)
+	{
+	  __pthread_unlock (&rwlock->__rw_lock);
+	  return EPERM;
+	}
+
+      --rwlock->__rw_readers;
+      if (rwlock->__rw_readers == 0)
+	/* Restart one waiting writer, if any.  */
+	th = dequeue (&rwlock->__rw_write_waiting);
+      else
+	th = NULL;
+
+      __pthread_unlock (&rwlock->__rw_lock);
+      if (th != NULL)
+	restart (th);
+
+      /* Recursive lock fixup */
+
+      if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_WRITER_NP)
+	{
+	  pthread_descr self = thread_self();
+	  pthread_readlock_info *victim = rwlock_remove_from_list(self, rwlock);
+
+	  if (victim != NULL)
+	    {
+	      if (victim->pr_lock_count == 0)
+		{
+		  victim->pr_next = self->p_readlock_free;
+		  self->p_readlock_free = victim;
+		}
+	    }
+	  else
+	    {
+	      if (self->p_untracked_readlock_count > 0)
+		self->p_untracked_readlock_count--;
+	    }
+	}
+    }
+
+  return 0;
+}
+
+
+
+int
+pthread_rwlockattr_init (pthread_rwlockattr_t *attr)
+{
+  attr->__lockkind = 0;
+  attr->__pshared = 0;
+
+  return 0;
+}
+
+
+int
+pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr attribute_unused)
+{
+  return 0;
+}
+
+
+int
+pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr, int *pshared)
+{
+  *pshared = attr->__pshared;
+  return 0;
+}
+
+
+int
+pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared)
+{
+  if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
+    return EINVAL;
+
+  attr->__pshared = pshared;
+
+  return 0;
+}
+
+
+int
+pthread_rwlockattr_getkind_np (const pthread_rwlockattr_t *attr, int *pref)
+{
+  *pref = attr->__lockkind;
+  return 0;
+}
+
+
+int
+pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *attr, int pref)
+{
+  if (pref != PTHREAD_RWLOCK_PREFER_READER_NP
+      && pref != PTHREAD_RWLOCK_PREFER_WRITER_NP
+      && pref != PTHREAD_RWLOCK_DEFAULT_NP)
+    return EINVAL;
+
+  attr->__lockkind = pref;
+
+  return 0;
+}

+ 299 - 0
libpthread/linuxthreads.old/semaphore.c

@@ -0,0 +1,299 @@
+/* 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.                 */
+
+/* Semaphores a la POSIX 1003.1b */
+
+#include <features.h>
+#include <limits.h>
+#include <errno.h>
+#include "pthread.h"
+#include "semaphore.h"
+#include "internals.h"
+#include "spinlock.h"
+#include "restart.h"
+#include "queue.h"
+
+int sem_init(sem_t *sem, int pshared, unsigned int value)
+{
+  if (value > SEM_VALUE_MAX) {
+    errno = EINVAL;
+    return -1;
+  }
+  if (pshared) {
+    errno = ENOSYS;
+    return -1;
+  }
+  __pthread_init_lock(&sem->__sem_lock);
+  sem->__sem_value = value;
+  sem->__sem_waiting = NULL;
+  return 0;
+}
+
+/* Function called by pthread_cancel to remove the thread from
+   waiting inside sem_wait. */
+
+static int new_sem_extricate_func(void *obj, pthread_descr th)
+{
+  volatile pthread_descr self = thread_self();
+  sem_t *sem = obj;
+  int did_remove = 0;
+
+  __pthread_lock(&sem->__sem_lock, self);
+  did_remove = remove_from_queue(&sem->__sem_waiting, th);
+  __pthread_unlock(&sem->__sem_lock);
+
+  return did_remove;
+}
+
+int sem_wait(sem_t * sem)
+{
+  volatile pthread_descr self = thread_self();
+  pthread_extricate_if extr;
+  int already_canceled = 0;
+  int spurious_wakeup_count;
+
+  /* Set up extrication interface */
+  extr.pu_object = sem;
+  extr.pu_extricate_func = new_sem_extricate_func;
+
+  __pthread_lock(&sem->__sem_lock, self);
+  if (sem->__sem_value > 0) {
+    sem->__sem_value--;
+    __pthread_unlock(&sem->__sem_lock);
+    return 0;
+  }
+  /* Register extrication interface */
+  THREAD_SETMEM(self, p_sem_avail, 0);
+  __pthread_set_own_extricate_if(self, &extr);
+  /* Enqueue only if not already cancelled. */
+  if (!(THREAD_GETMEM(self, p_canceled)
+      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE))
+    enqueue(&sem->__sem_waiting, self);
+  else
+    already_canceled = 1;
+  __pthread_unlock(&sem->__sem_lock);
+
+  if (already_canceled) {
+    __pthread_set_own_extricate_if(self, 0);
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+  }
+
+  /* Wait for sem_post or cancellation, or fall through if already canceled */
+  spurious_wakeup_count = 0;
+  while (1)
+    {
+      suspend(self);
+      if (THREAD_GETMEM(self, p_sem_avail) == 0
+	  && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
+	      || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
+	{
+	  /* Count resumes that don't belong to us. */
+	  spurious_wakeup_count++;
+	  continue;
+	}
+      break;
+    }
+  __pthread_set_own_extricate_if(self, 0);
+
+  /* Terminate only if the wakeup came from cancellation. */
+  /* Otherwise ignore cancellation because we got the semaphore. */
+
+  if (THREAD_GETMEM(self, p_woken_by_cancel)
+      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
+    THREAD_SETMEM(self, p_woken_by_cancel, 0);
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+  }
+  /* We got the semaphore */
+  return 0;
+}
+
+int sem_trywait(sem_t * sem)
+{
+  int retval;
+
+  __pthread_lock(&sem->__sem_lock, NULL);
+  if (sem->__sem_value == 0) {
+    errno = EAGAIN;
+    retval = -1;
+  } else {
+    sem->__sem_value--;
+    retval = 0;
+  }
+  __pthread_unlock(&sem->__sem_lock);
+  return retval;
+}
+
+int sem_post(sem_t * sem)
+{
+  pthread_descr self = thread_self();
+  pthread_descr th;
+  struct pthread_request request;
+
+  if (THREAD_GETMEM(self, p_in_sighandler) == NULL) {
+    __pthread_lock(&sem->__sem_lock, self);
+    if (sem->__sem_waiting == NULL) {
+      if (sem->__sem_value >= SEM_VALUE_MAX) {
+        /* Overflow */
+        errno = ERANGE;
+        __pthread_unlock(&sem->__sem_lock);
+        return -1;
+      }
+      sem->__sem_value++;
+      __pthread_unlock(&sem->__sem_lock);
+    } else {
+      th = dequeue(&sem->__sem_waiting);
+      __pthread_unlock(&sem->__sem_lock);
+      th->p_sem_avail = 1;
+      WRITE_MEMORY_BARRIER();
+      restart(th);
+    }
+  } else {
+    /* If we're in signal handler, delegate post operation to
+       the thread manager. */
+    if (__pthread_manager_request < 0) {
+      if (__pthread_initialize_manager() < 0) {
+        errno = EAGAIN;
+        return -1;
+      }
+    }
+    request.req_kind = REQ_POST;
+    request.req_args.post = sem;
+    TEMP_FAILURE_RETRY(write(__pthread_manager_request,
+				    (char *) &request, sizeof(request)));
+  }
+  return 0;
+}
+
+int sem_getvalue(sem_t * sem, int * sval)
+{
+  *sval = sem->__sem_value;
+  return 0;
+}
+
+int sem_destroy(sem_t * sem)
+{
+  if (sem->__sem_waiting != NULL) {
+    __set_errno (EBUSY);
+    return -1;
+  }
+  return 0;
+}
+
+sem_t *sem_open(const char *name attribute_unused, int oflag attribute_unused, ...)
+{
+  __set_errno (ENOSYS);
+  return SEM_FAILED;
+}
+
+int sem_close(sem_t *sem attribute_unused)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+int sem_unlink(const char *name attribute_unused)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+int sem_timedwait(sem_t *sem, const struct timespec *abstime)
+{
+  pthread_descr self = thread_self();
+  pthread_extricate_if extr;
+  int already_canceled = 0;
+  int spurious_wakeup_count;
+
+  __pthread_lock(&sem->__sem_lock, self);
+  if (sem->__sem_value > 0) {
+    --sem->__sem_value;
+    __pthread_unlock(&sem->__sem_lock);
+    return 0;
+  }
+
+  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) {
+    /* The standard requires that if the function would block and the
+       time value is illegal, the function returns with an error.  */
+    __pthread_unlock(&sem->__sem_lock);
+    __set_errno (EINVAL);
+    return -1;
+  }
+
+  /* Set up extrication interface */
+  extr.pu_object = sem;
+  extr.pu_extricate_func = new_sem_extricate_func;
+
+  /* Register extrication interface */
+  THREAD_SETMEM(self, p_sem_avail, 0);
+  __pthread_set_own_extricate_if(self, &extr);
+  /* Enqueue only if not already cancelled. */
+  if (!(THREAD_GETMEM(self, p_canceled)
+      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE))
+    enqueue(&sem->__sem_waiting, self);
+  else
+    already_canceled = 1;
+  __pthread_unlock(&sem->__sem_lock);
+
+  if (already_canceled) {
+    __pthread_set_own_extricate_if(self, 0);
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+  }
+
+  spurious_wakeup_count = 0;
+  while (1)
+    {
+      if (timedsuspend(self, abstime) == 0) {
+	int was_on_queue;
+
+	/* __pthread_lock will queue back any spurious restarts that
+	   may happen to it. */
+
+	__pthread_lock(&sem->__sem_lock, self);
+	was_on_queue = remove_from_queue(&sem->__sem_waiting, self);
+	__pthread_unlock(&sem->__sem_lock);
+
+	if (was_on_queue) {
+	  __pthread_set_own_extricate_if(self, 0);
+	  __set_errno (ETIMEDOUT);
+	  return -1;
+	}
+
+	/* Eat the outstanding restart() from the signaller */
+	suspend(self);
+      }
+
+      if (THREAD_GETMEM(self, p_sem_avail) == 0
+	  && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
+	      || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
+	{
+	  /* Count resumes that don't belong to us. */
+	  spurious_wakeup_count++;
+	  continue;
+	}
+      break;
+    }
+
+ __pthread_set_own_extricate_if(self, 0);
+
+  /* Terminate only if the wakeup came from cancellation. */
+  /* Otherwise ignore cancellation because we got the semaphore. */
+
+  if (THREAD_GETMEM(self, p_woken_by_cancel)
+      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
+    THREAD_SETMEM(self, p_woken_by_cancel, 0);
+    __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+  }
+  /* We got the semaphore */
+  return 0;
+}

+ 97 - 0
libpthread/linuxthreads.old/semaphore.h

@@ -0,0 +1,97 @@
+/* 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.                 */
+
+#ifndef _SEMAPHORE_H
+#define _SEMAPHORE_H	1
+
+#include <features.h>
+#include <sys/types.h>
+#include <limits.h>
+#ifdef __USE_XOPEN2K
+# define __need_timespec
+# include <time.h>
+#endif
+
+#ifndef _PTHREAD_DESCR_DEFINED
+/* Thread descriptors.  Needed for `sem_t' definition.  */
+typedef struct _pthread_descr_struct *_pthread_descr;
+# define _PTHREAD_DESCR_DEFINED
+#endif
+
+/* System specific semaphore definition.  */
+typedef struct
+{
+  struct _pthread_fastlock __sem_lock;
+  int __sem_value;
+  _pthread_descr __sem_waiting;
+} sem_t;
+
+
+
+/* Value returned if `sem_open' failed.  */
+#define SEM_FAILED	((sem_t *) 0)
+
+/* Maximum value the semaphore can have.  */
+#ifndef SEM_VALUE_MAX
+#define SEM_VALUE_MAX	((int) ((~0u) >> 1))
+#endif
+
+
+__BEGIN_DECLS
+
+/* Initialize semaphore object SEM to VALUE.  If PSHARED then share it
+   with other processes.  */
+extern int sem_init (sem_t *__sem, int __pshared, unsigned int __value) __THROW;
+
+/* Free resources associated with semaphore object SEM.  */
+extern int sem_destroy (sem_t *__sem) __THROW;
+
+/* Open a named semaphore NAME with open flags OFLAG.  */
+extern sem_t *sem_open (const char *__name, int __oflag, ...) __THROW;
+
+/* Close descriptor for named semaphore SEM.  */
+extern int sem_close (sem_t *__sem) __THROW;
+
+/* Remove named semaphore NAME.  */
+extern int sem_unlink (const char *__name) __THROW;
+
+/* Wait for SEM being posted.
+
+   This function is a cancellation point and therefore not marked with
+   __THROW.  */
+extern int sem_wait (sem_t *__sem);
+
+#ifdef __USE_XOPEN2K
+/* Similar to `sem_wait' but wait only until ABSTIME.
+
+   This function is a cancellation point and therefore not marked with
+   __THROW.  */
+extern int sem_timedwait (sem_t *__restrict __sem,
+			  const struct timespec *__restrict __abstime);
+#endif
+
+/* Test whether SEM is posted.  */
+extern int sem_trywait (sem_t *__sem) __THROW;
+
+/* Post SEM.  */
+extern int sem_post (sem_t *__sem) __THROW;
+
+/* Get current value of SEM and store it in *SVAL.  */
+extern int sem_getvalue (sem_t *__restrict __sem, int *__restrict __sval)
+     __THROW;
+
+
+__END_DECLS
+
+#endif	/* semaphore.h */

+ 246 - 0
libpthread/linuxthreads.old/signals.c

@@ -0,0 +1,246 @@
+/* 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.                 */
+
+/* Handling of signals */
+
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include "pthread.h"
+#include "internals.h"
+#include "spinlock.h"
+#include <bits/sigcontextinfo.h>
+
+int pthread_sigmask(int how, const sigset_t * newmask, sigset_t * oldmask)
+{
+  sigset_t mask;
+
+  if (newmask != NULL) {
+    mask = *newmask;
+    /* Don't allow __pthread_sig_restart to be unmasked.
+       Don't allow __pthread_sig_cancel to be masked. */
+    switch(how) {
+    case SIG_SETMASK:
+      sigaddset(&mask, __pthread_sig_restart);
+      sigdelset(&mask, __pthread_sig_cancel);
+      if (__pthread_sig_debug > 0)
+	sigdelset(&mask, __pthread_sig_debug);
+      break;
+    case SIG_BLOCK:
+      sigdelset(&mask, __pthread_sig_cancel);
+      if (__pthread_sig_debug > 0)
+	sigdelset(&mask, __pthread_sig_debug);
+      break;
+    case SIG_UNBLOCK:
+      sigdelset(&mask, __pthread_sig_restart);
+      break;
+    }
+    newmask = &mask;
+  }
+  if (sigprocmask(how, newmask, oldmask) == -1)
+    return errno;
+  else
+    return 0;
+}
+
+int pthread_kill(pthread_t thread, int signo)
+{
+  pthread_handle handle = thread_handle(thread);
+  int pid;
+
+  __pthread_lock(&handle->h_lock, NULL);
+  if (invalid_handle(handle, thread)) {
+    __pthread_unlock(&handle->h_lock);
+    return ESRCH;
+  }
+  pid = handle->h_descr->p_pid;
+  __pthread_unlock(&handle->h_lock);
+  if (kill(pid, signo) == -1)
+    return errno;
+  else
+    return 0;
+}
+
+/* User-provided signal handlers */
+typedef void (*arch_sighandler_t) __PMT ((int, SIGCONTEXT));
+static union
+{
+  arch_sighandler_t old;
+  void (*rt) (int, struct siginfo *, struct ucontext *);
+} sighandler[NSIG];
+
+/* The wrapper around user-provided signal handlers */
+static void pthread_sighandler(int signo, SIGCONTEXT ctx)
+{
+  pthread_descr self = thread_self();
+  char * in_sighandler;
+  /* If we're in a sigwait operation, just record the signal received
+     and return without calling the user's handler */
+  if (THREAD_GETMEM(self, p_sigwaiting)) {
+    THREAD_SETMEM(self, p_sigwaiting, 0);
+    THREAD_SETMEM(self, p_signal, signo);
+    return;
+  }
+  /* Record that we're in a signal handler and call the user's
+     handler function */
+  in_sighandler = THREAD_GETMEM(self, p_in_sighandler);
+  if (in_sighandler == NULL)
+    THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME);
+  sighandler[signo].old(signo, SIGCONTEXT_EXTRA_ARGS ctx);
+  if (in_sighandler == NULL)
+    THREAD_SETMEM(self, p_in_sighandler, NULL);
+}
+
+/* The same, this time for real-time signals.  */
+static void pthread_sighandler_rt(int signo, struct siginfo *si,
+				  struct ucontext *uc)
+{
+  pthread_descr self = thread_self();
+  char * in_sighandler;
+  /* If we're in a sigwait operation, just record the signal received
+     and return without calling the user's handler */
+  if (THREAD_GETMEM(self, p_sigwaiting)) {
+    THREAD_SETMEM(self, p_sigwaiting, 0);
+    THREAD_SETMEM(self, p_signal, signo);
+    return;
+  }
+  /* Record that we're in a signal handler and call the user's
+     handler function */
+  in_sighandler = THREAD_GETMEM(self, p_in_sighandler);
+  if (in_sighandler == NULL)
+    THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME);
+  sighandler[signo].rt(signo, si, uc);
+  if (in_sighandler == NULL)
+    THREAD_SETMEM(self, p_in_sighandler, NULL);
+}
+
+/* The wrapper around sigaction.  Install our own signal handler
+   around the signal. */
+libpthread_hidden_proto(sigaction)
+int sigaction(int sig, const struct sigaction * act,
+              struct sigaction * oact)
+{
+  struct sigaction newact;
+  struct sigaction *newactp;
+
+#ifdef DEBUG_PT
+printf(__FUNCTION__": pthreads wrapper!\n");
+#endif
+  if (sig == __pthread_sig_restart ||
+      sig == __pthread_sig_cancel ||
+      (sig == __pthread_sig_debug && __pthread_sig_debug > 0))
+    return EINVAL;
+  if (act)
+    {
+      newact = *act;
+      if (act->sa_handler != SIG_IGN && act->sa_handler != SIG_DFL
+	  && sig > 0 && sig < NSIG)
+	{
+	  if (act->sa_flags & SA_SIGINFO)
+	    newact.sa_handler = (__sighandler_t) pthread_sighandler_rt;
+	  else
+	    newact.sa_handler = (__sighandler_t) pthread_sighandler;
+	}
+      newactp = &newact;
+    }
+  else
+    newactp = NULL;
+  if (__libc_sigaction(sig, newactp, oact) == -1)
+    return -1;
+#ifdef DEBUG_PT
+printf(__FUNCTION__": sighandler installed, sigaction successful\n");
+#endif
+  if (sig > 0 && sig < NSIG)
+    {
+      if (oact != NULL)
+	oact->sa_handler = (__sighandler_t) sighandler[sig].old;
+      if (act)
+	/* For the assignment is does not matter whether it's a normal
+	   or real-time signal.  */
+	sighandler[sig].old = (arch_sighandler_t) act->sa_handler;
+    }
+  return 0;
+}
+libpthread_hidden_def(sigaction)
+
+/* A signal handler that does nothing */
+static void pthread_null_sighandler(int sig attribute_unused) { }
+
+/* sigwait -- synchronously wait for a signal */
+int sigwait(const sigset_t * set, int * sig)
+{
+  volatile pthread_descr self = thread_self();
+  sigset_t mask;
+  int s;
+  sigjmp_buf jmpbuf;
+  struct sigaction sa;
+
+  /* Get ready to block all signals except those in set
+     and the cancellation signal.
+     Also check that handlers are installed on all signals in set,
+     and if not, install our dummy handler.  This is conformant to
+     POSIX: "The effect of sigwait() on the signal actions for the
+     signals in set is unspecified." */
+  __sigfillset(&mask);
+  sigdelset(&mask, __pthread_sig_cancel);
+  for (s = 1; s <= NSIG; s++) {
+    if (sigismember(set, s) &&
+        s != __pthread_sig_restart &&
+        s != __pthread_sig_cancel &&
+        s != __pthread_sig_debug) {
+      sigdelset(&mask, s);
+      if (sighandler[s].old == NULL ||
+	  sighandler[s].old == (arch_sighandler_t) SIG_DFL ||
+	  sighandler[s].old == (arch_sighandler_t) SIG_IGN) {
+        memset(&sa, 0, sizeof(sa));
+        sa.sa_handler = pthread_null_sighandler;
+        sigaction(s, &sa, NULL);
+      }
+    }
+  }
+  /* Test for cancellation */
+  if (sigsetjmp(jmpbuf, 1) == 0) {
+    THREAD_SETMEM(self, p_cancel_jmp, &jmpbuf);
+    if (! (THREAD_GETMEM(self, p_canceled)
+	   && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) {
+      /* Reset the signal count */
+      THREAD_SETMEM(self, p_signal, 0);
+      /* Say we're in sigwait */
+      THREAD_SETMEM(self, p_sigwaiting, 1);
+      /* Unblock the signals and wait for them */
+      sigsuspend(&mask);
+    }
+  }
+  THREAD_SETMEM(self, p_cancel_jmp, NULL);
+  /* The signals are now reblocked.  Check for cancellation */
+  pthread_testcancel();
+  /* We should have self->p_signal != 0 and equal to the signal received */
+  *sig = THREAD_GETMEM(self, p_signal);
+  return 0;
+}
+
+/* Redefine raise() to send signal to calling thread only,
+   as per POSIX 1003.1c */
+libpthread_hidden_proto(raise)
+int raise (int sig)
+{
+  int retcode = pthread_kill(pthread_self(), sig);
+  if (retcode == 0)
+    return 0;
+  else {
+    errno = retcode;
+    return -1;
+  }
+}
+libpthread_hidden_def(raise)

+ 198 - 0
libpthread/linuxthreads.old/specific.c

@@ -0,0 +1,198 @@
+/* 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.                 */
+
+/* Thread-specific data */
+
+#include <features.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include "pthread.h"
+#include "internals.h"
+#include "spinlock.h"
+#include "restart.h"
+
+/* Table of keys. */
+
+static struct pthread_key_struct pthread_keys[PTHREAD_KEYS_MAX] =
+  { { 0, NULL } };
+
+/* For debugging purposes put the maximum number of keys in a variable.  */
+const int __linuxthreads_pthread_keys_max = PTHREAD_KEYS_MAX;
+const int __linuxthreads_pthread_key_2ndlevel_size = PTHREAD_KEY_2NDLEVEL_SIZE;
+
+/* Mutex to protect access to pthread_keys */
+
+static pthread_mutex_t pthread_keys_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/* Create a new key */
+
+int pthread_key_create(pthread_key_t * key, destr_function destr)
+{
+  int i;
+
+  __pthread_mutex_lock(&pthread_keys_mutex);
+  for (i = 0; i < PTHREAD_KEYS_MAX; i++) {
+    if (! pthread_keys[i].in_use) {
+      /* Mark key in use */
+      pthread_keys[i].in_use = 1;
+      pthread_keys[i].destr = destr;
+      __pthread_mutex_unlock(&pthread_keys_mutex);
+      *key = i;
+      return 0;
+    }
+  }
+  __pthread_mutex_unlock(&pthread_keys_mutex);
+  return EAGAIN;
+}
+
+/* Delete a key */
+int pthread_key_delete(pthread_key_t key)
+{
+    pthread_descr self = thread_self();
+
+    __pthread_mutex_lock(&pthread_keys_mutex);
+    if (key >= PTHREAD_KEYS_MAX || !pthread_keys[key].in_use) {
+	__pthread_mutex_unlock(&pthread_keys_mutex);
+	return EINVAL;
+    }
+    pthread_keys[key].in_use = 0;
+    pthread_keys[key].destr = NULL;
+
+    /* Set the value of the key to NULL in all running threads, so
+       that if the key is reallocated later by pthread_key_create, its
+       associated values will be NULL in all threads.
+       Do nothing if no threads have been created yet.  */
+    if (__pthread_manager_request != -1)
+    {
+	pthread_descr th;
+	unsigned int idx1st, idx2nd;
+
+	idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE;
+	idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE;
+	th = self;
+	do {
+	    /* If the thread already is terminated don't modify the memory.  */
+	    if (!th->p_terminated && th->p_specific[idx1st] != NULL)
+		th->p_specific[idx1st][idx2nd] = NULL;
+	    th = th->p_nextlive;
+	} while (th != self);
+    }
+
+    __pthread_mutex_unlock(&pthread_keys_mutex);
+    return 0;
+}
+
+/* Set the value of a key */
+
+int pthread_setspecific(pthread_key_t key, const void * pointer)
+{
+    pthread_descr self = thread_self();
+    unsigned int idx1st, idx2nd;
+
+    if (key >= PTHREAD_KEYS_MAX || !pthread_keys[key].in_use)
+	return EINVAL;
+    idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE;
+    idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE;
+    if (THREAD_GETMEM_NC(self, p_specific[idx1st]) == NULL) {
+	void *newp = calloc(PTHREAD_KEY_2NDLEVEL_SIZE, sizeof (void *));
+	if (newp == NULL)
+	    return ENOMEM;
+	THREAD_SETMEM_NC(self, p_specific[idx1st], newp);
+    }
+    THREAD_GETMEM_NC(self, p_specific[idx1st])[idx2nd] = (void *) pointer;
+    return 0;
+}
+
+/* Get the value of a key */
+
+void * pthread_getspecific(pthread_key_t key)
+{
+    pthread_descr self = thread_self();
+    unsigned int idx1st, idx2nd;
+
+    if (key >= PTHREAD_KEYS_MAX)
+	return NULL;
+    idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE;
+    idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE;
+    if (THREAD_GETMEM_NC(self, p_specific[idx1st]) == NULL
+	    || !pthread_keys[key].in_use)
+	return NULL;
+    return THREAD_GETMEM_NC(self, p_specific[idx1st])[idx2nd];
+}
+
+/* Call the destruction routines on all keys */
+
+void __pthread_destroy_specifics(void)
+{
+    pthread_descr self = thread_self();
+    int i, j, round, found_nonzero;
+    destr_function destr;
+    void * data;
+
+    for (round = 0, found_nonzero = 1;
+	    found_nonzero && round < PTHREAD_DESTRUCTOR_ITERATIONS;
+	    round++) {
+	found_nonzero = 0;
+	for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++)
+	    if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL)
+		for (j = 0; j < PTHREAD_KEY_2NDLEVEL_SIZE; j++) {
+		    destr = pthread_keys[i * PTHREAD_KEY_2NDLEVEL_SIZE + j].destr;
+		    data = THREAD_GETMEM_NC(self, p_specific[i])[j];
+		    if (destr != NULL && data != NULL) {
+			THREAD_GETMEM_NC(self, p_specific[i])[j] = NULL;
+			destr(data);
+			found_nonzero = 1;
+		    }
+		}
+    }
+    __pthread_lock(THREAD_GETMEM(self, p_lock), self);
+    for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++) {
+	if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL) {
+	    free(THREAD_GETMEM_NC(self, p_specific[i]));
+	    THREAD_SETMEM_NC(self, p_specific[i], NULL);
+	}
+    }
+    __pthread_unlock(THREAD_GETMEM(self, p_lock));
+}
+
+#if !defined __UCLIBC_HAS_TLS__ && defined __UCLIBC_HAS_RPC__
+
+/* Thread-specific data for libc. */
+
+int
+__pthread_internal_tsd_set (int key, const void * pointer)
+{
+  pthread_descr self = thread_self();
+
+  THREAD_SETMEM_NC(self, p_libc_specific[key], (void *) pointer);
+  return 0;
+}
+
+void *
+__pthread_internal_tsd_get (int key)
+{
+  pthread_descr self = thread_self();
+
+  return THREAD_GETMEM_NC(self, p_libc_specific[key]);
+}
+
+void ** __attribute__ ((__const__))
+__pthread_internal_tsd_address (int key)
+{
+  pthread_descr self = thread_self();
+  return &self->p_libc_specific[key];
+}
+
+#endif

+ 720 - 0
libpthread/linuxthreads.old/spinlock.c

@@ -0,0 +1,720 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1998 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.                 */
+
+/* Internal locks */
+
+#include <errno.h>
+#include <sched.h>
+#include <time.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "pthread.h"
+#include "internals.h"
+#include "spinlock.h"
+#include "restart.h"
+
+libpthread_hidden_proto(nanosleep)
+
+static void __pthread_acquire(int * spinlock);
+
+static __inline__ void __pthread_release(int * spinlock)
+{
+  WRITE_MEMORY_BARRIER();
+  *spinlock = __LT_SPINLOCK_INIT;
+  __asm__ __volatile__ ("" : "=m" (*spinlock) : "m" (*spinlock));
+}
+
+
+/* The status field of a spinlock is a pointer whose least significant
+   bit is a locked flag.
+
+   Thus the field values have the following meanings:
+
+   status == 0:       spinlock is free
+   status == 1:       spinlock is taken; no thread is waiting on it
+
+   (status & 1) == 1: spinlock is taken and (status & ~1L) is a
+                      pointer to the first waiting thread; other
+		      waiting threads are linked via the p_nextlock
+		      field.
+   (status & 1) == 0: same as above, but spinlock is not taken.
+
+   The waiting list is not sorted by priority order.
+   Actually, we always insert at top of list (sole insertion mode
+   that can be performed without locking).
+   For __pthread_unlock, we perform a linear search in the list
+   to find the highest-priority, oldest waiting thread.
+   This is safe because there are no concurrent __pthread_unlock
+   operations -- only the thread that locked the mutex can unlock it. */
+
+
+void internal_function __pthread_lock(struct _pthread_fastlock * lock,
+				      pthread_descr self)
+{
+#if defined HAS_COMPARE_AND_SWAP
+  long oldstatus, newstatus;
+  int successful_seizure, spurious_wakeup_count;
+#endif
+
+#if defined TEST_FOR_COMPARE_AND_SWAP
+  if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+  {
+    __pthread_acquire(&lock->__spinlock);
+    return;
+  }
+#endif
+
+#if defined HAS_COMPARE_AND_SWAP
+  /* First try it without preparation.  Maybe it's a completely
+     uncontested lock.  */
+  if (lock->__status == 0 && __compare_and_swap (&lock->__status, 0, 1))
+    return;
+
+  spurious_wakeup_count = 0;
+
+  /* On SMP, try spinning to get the lock. */
+#if 0
+  if (__pthread_smp_kernel) {
+    int spin_count;
+    int max_count = lock->__spinlock * 2 + 10;
+
+    if (max_count > MAX_ADAPTIVE_SPIN_COUNT)
+      max_count = MAX_ADAPTIVE_SPIN_COUNT;
+
+    for (spin_count = 0; spin_count < max_count; spin_count++) {
+      if (((oldstatus = lock->__status) & 1) == 0) {
+	if(__compare_and_swap(&lock->__status, oldstatus, oldstatus | 1))
+	{
+	  if (spin_count)
+	    lock->__spinlock += (spin_count - lock->__spinlock) / 8;
+	  READ_MEMORY_BARRIER();
+	  return;
+	}
+      }
+#ifdef BUSY_WAIT_NOP
+      BUSY_WAIT_NOP;
+#endif
+      __asm__ __volatile__ ("" : "=m" (lock->__status) : "m" (lock->__status));
+    }
+
+    lock->__spinlock += (spin_count - lock->__spinlock) / 8;
+  }
+#endif
+
+again:
+
+  /* No luck, try once more or suspend. */
+
+  do {
+    oldstatus = lock->__status;
+    successful_seizure = 0;
+
+    if ((oldstatus & 1) == 0) {
+      newstatus = oldstatus | 1;
+      successful_seizure = 1;
+    } else {
+      if (self == NULL)
+	self = thread_self();
+      newstatus = (long) self | 1;
+    }
+
+    if (self != NULL) {
+      THREAD_SETMEM(self, p_nextlock, (pthread_descr) (oldstatus));
+      /* Make sure the store in p_nextlock completes before performing
+         the compare-and-swap */
+      MEMORY_BARRIER();
+    }
+  } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus));
+
+  /* Suspend with guard against spurious wakeup.
+     This can happen in pthread_cond_timedwait_relative, when the thread
+     wakes up due to timeout and is still on the condvar queue, and then
+     locks the queue to remove itself. At that point it may still be on the
+     queue, and may be resumed by a condition signal. */
+
+  if (!successful_seizure) {
+    for (;;) {
+      suspend(self);
+      if (self->p_nextlock != NULL) {
+	/* Count resumes that don't belong to us. */
+	spurious_wakeup_count++;
+	continue;
+      }
+      break;
+    }
+    goto again;
+  }
+
+  /* Put back any resumes we caught that don't belong to us. */
+  while (spurious_wakeup_count--)
+    restart(self);
+
+  READ_MEMORY_BARRIER();
+#endif
+}
+
+int __pthread_unlock(struct _pthread_fastlock * lock)
+{
+#if defined HAS_COMPARE_AND_SWAP
+  long oldstatus;
+  pthread_descr thr, * ptr, * maxptr;
+  int maxprio;
+#endif
+
+#if defined TEST_FOR_COMPARE_AND_SWAP
+  if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+  {
+    __pthread_release(&lock->__spinlock);
+    return 0;
+  }
+#endif
+
+#if defined HAS_COMPARE_AND_SWAP
+  WRITE_MEMORY_BARRIER();
+
+again:
+  while ((oldstatus = lock->__status) == 1) {
+    if (__compare_and_swap_with_release_semantics(&lock->__status,
+	oldstatus, 0))
+      return 0;
+  }
+
+  /* Find thread in waiting queue with maximal priority */
+  ptr = (pthread_descr *) &lock->__status;
+  thr = (pthread_descr) (oldstatus & ~1L);
+  maxprio = 0;
+  maxptr = ptr;
+
+  /* Before we iterate over the wait queue, we need to execute
+     a read barrier, otherwise we may read stale contents of nodes that may
+     just have been inserted by other processors. One read barrier is enough to
+     ensure we have a stable list; we don't need one for each pointer chase
+     through the list, because we are the owner of the lock; other threads
+     can only add nodes at the front; if a front node is consistent,
+     the ones behind it must also be. */
+
+  READ_MEMORY_BARRIER();
+
+  while (thr != 0) {
+    if (thr->p_priority >= maxprio) {
+      maxptr = ptr;
+      maxprio = thr->p_priority;
+    }
+    ptr = &(thr->p_nextlock);
+    thr = (pthread_descr)((long)(thr->p_nextlock) & ~1L);
+  }
+
+  /* Remove max prio thread from waiting list. */
+  if (maxptr == (pthread_descr *) &lock->__status) {
+    /* If max prio thread is at head, remove it with compare-and-swap
+       to guard against concurrent lock operation. This removal
+       also has the side effect of marking the lock as released
+       because the new status comes from thr->p_nextlock whose
+       least significant bit is clear. */
+    thr = (pthread_descr) (oldstatus & ~1L);
+    if (! __compare_and_swap_with_release_semantics
+	    (&lock->__status, oldstatus, (long)(thr->p_nextlock) & ~1L))
+      goto again;
+  } else {
+    /* No risk of concurrent access, remove max prio thread normally.
+       But in this case we must also flip the least significant bit
+       of the status to mark the lock as released. */
+    thr = (pthread_descr)((long)*maxptr & ~1L);
+    *maxptr = thr->p_nextlock;
+
+    /* Ensure deletion from linked list completes before we
+       release the lock. */
+    WRITE_MEMORY_BARRIER();
+
+    do {
+      oldstatus = lock->__status;
+    } while (!__compare_and_swap_with_release_semantics(&lock->__status,
+	     oldstatus, oldstatus & ~1L));
+  }
+
+  /* Wake up the selected waiting thread. Woken thread can check
+     its own p_nextlock field for NULL to detect that it has been removed. No
+     barrier is needed here, since restart() and suspend() take
+     care of memory synchronization. */
+
+  thr->p_nextlock = NULL;
+  restart(thr);
+
+  return 0;
+#endif
+}
+
+/*
+ * Alternate fastlocks do not queue threads directly. Instead, they queue
+ * these wait queue node structures. When a timed wait wakes up due to
+ * a timeout, it can leave its wait node in the queue (because there
+ * is no safe way to remove from the quue). Some other thread will
+ * deallocate the abandoned node.
+ */
+
+
+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 */
+};
+
+static long wait_node_free_list;
+static int wait_node_free_list_spinlock;
+
+/* 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
+   assumption here is that we can safely access wait_node_free_list->next.
+   That's because we never free nodes once we allocate them, so a pointer to a
+   node remains valid indefinitely. */
+
+static struct wait_node *wait_node_alloc(void)
+{
+    struct wait_node *new_node = 0;
+
+    __pthread_acquire(&wait_node_free_list_spinlock);
+    if (wait_node_free_list != 0) {
+      new_node = (struct wait_node *) wait_node_free_list;
+      wait_node_free_list = (long) new_node->next;
+    }
+    WRITE_MEMORY_BARRIER();
+    __pthread_release(&wait_node_free_list_spinlock);
+
+    if (new_node == 0)
+      return malloc(sizeof *wait_node_alloc());
+
+    return new_node;
+}
+
+/* Return a node to the head of the free list using an atomic
+   operation. */
+
+static void wait_node_free(struct wait_node *wn)
+{
+    __pthread_acquire(&wait_node_free_list_spinlock);
+    wn->next = (struct wait_node *) wait_node_free_list;
+    wait_node_free_list = (long) wn;
+    WRITE_MEMORY_BARRIER();
+    __pthread_release(&wait_node_free_list_spinlock);
+    return;
+}
+
+#if defined HAS_COMPARE_AND_SWAP
+
+/* Remove a wait node from the specified queue.  It is assumed
+   that the removal takes place concurrently with only atomic insertions at the
+   head of the queue. */
+
+static void wait_node_dequeue(struct wait_node **pp_head,
+			      struct wait_node **pp_node,
+			      struct wait_node *p_node)
+{
+  /* If the node is being deleted from the head of the
+     list, it must be deleted using atomic compare-and-swap.
+     Otherwise it can be deleted in the straightforward way. */
+
+  if (pp_node == pp_head) {
+    /* We don't need a read barrier between these next two loads,
+       because it is assumed that the caller has already ensured
+       the stability of *p_node with respect to p_node. */
+
+    long oldvalue = (long) p_node;
+    long newvalue = (long) p_node->next;
+
+    if (__compare_and_swap((long *) pp_node, oldvalue, newvalue))
+      return;
+
+    /* Oops! Compare and swap failed, which means the node is
+       no longer first. We delete it using the ordinary method.  But we don't
+       know the identity of the node which now holds the pointer to the node
+       being deleted, so we must search from the beginning. */
+
+    for (pp_node = pp_head; p_node != *pp_node; ) {
+      pp_node = &(*pp_node)->next;
+      READ_MEMORY_BARRIER(); /* Stabilize *pp_node for next iteration. */
+    }
+  }
+
+  *pp_node = p_node->next;
+  return;
+}
+
+#endif
+
+void __pthread_alt_lock(struct _pthread_fastlock * lock,
+		        pthread_descr self)
+{
+#if defined HAS_COMPARE_AND_SWAP
+  long oldstatus, newstatus;
+#endif
+  struct wait_node wait_node;
+
+#if defined TEST_FOR_COMPARE_AND_SWAP
+  if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+  {
+    int suspend_needed = 0;
+    __pthread_acquire(&lock->__spinlock);
+
+    if (lock->__status == 0)
+      lock->__status = 1;
+    else {
+      if (self == NULL)
+	self = thread_self();
+
+      wait_node.abandoned = 0;
+      wait_node.next = (struct wait_node *) lock->__status;
+      wait_node.thr = self;
+      lock->__status = (long) &wait_node;
+      suspend_needed = 1;
+    }
+
+    __pthread_release(&lock->__spinlock);
+
+    if (suspend_needed)
+      suspend (self);
+    return;
+  }
+#endif
+
+#if defined HAS_COMPARE_AND_SWAP
+  do {
+    oldstatus = lock->__status;
+    if (oldstatus == 0) {
+      newstatus = 1;
+    } else {
+      if (self == NULL)
+	self = thread_self();
+      wait_node.thr = self;
+      newstatus = (long) &wait_node;
+    }
+    wait_node.abandoned = 0;
+    wait_node.next = (struct wait_node *) oldstatus;
+    /* Make sure the store in wait_node.next completes before performing
+       the compare-and-swap */
+    MEMORY_BARRIER();
+  } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus));
+
+  /* Suspend. Note that unlike in __pthread_lock, we don't worry
+     here about spurious wakeup. That's because this lock is not
+     used in situations where that can happen; the restart can
+     only come from the previous lock owner. */
+
+  if (oldstatus != 0)
+    suspend(self);
+
+  READ_MEMORY_BARRIER();
+#endif
+}
+
+/* Timed-out lock operation; returns 0 to indicate timeout. */
+
+int __pthread_alt_timedlock(struct _pthread_fastlock * lock,
+			    pthread_descr self, const struct timespec *abstime)
+{
+  long oldstatus = 0;
+#if defined HAS_COMPARE_AND_SWAP
+  long newstatus;
+#endif
+  struct wait_node *p_wait_node = wait_node_alloc();
+
+  /* Out of memory, just give up and do ordinary lock. */
+  if (p_wait_node == 0) {
+    __pthread_alt_lock(lock, self);
+    return 1;
+  }
+
+#if defined TEST_FOR_COMPARE_AND_SWAP
+  if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+  {
+    __pthread_acquire(&lock->__spinlock);
+
+    if (lock->__status == 0)
+      lock->__status = 1;
+    else {
+      if (self == NULL)
+	self = thread_self();
+
+      p_wait_node->abandoned = 0;
+      p_wait_node->next = (struct wait_node *) lock->__status;
+      p_wait_node->thr = self;
+      lock->__status = (long) p_wait_node;
+      oldstatus = 1; /* force suspend */
+    }
+
+    __pthread_release(&lock->__spinlock);
+    goto suspend;
+  }
+#endif
+
+#if defined HAS_COMPARE_AND_SWAP
+  do {
+    oldstatus = lock->__status;
+    if (oldstatus == 0) {
+      newstatus = 1;
+    } else {
+      if (self == NULL)
+	self = thread_self();
+      p_wait_node->thr = self;
+      newstatus = (long) p_wait_node;
+    }
+    p_wait_node->abandoned = 0;
+    p_wait_node->next = (struct wait_node *) oldstatus;
+    /* Make sure the store in wait_node.next completes before performing
+       the compare-and-swap */
+    MEMORY_BARRIER();
+  } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus));
+#endif
+
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+  suspend:
+#endif
+
+  /* If we did not get the lock, do a timed suspend. If we wake up due
+     to a timeout, then there is a race; the old lock owner may try
+     to remove us from the queue. This race is resolved by us and the owner
+     doing an atomic testandset() to change the state of the wait node from 0
+     to 1. If we succeed, then it's a timeout and we abandon the node in the
+     queue. If we fail, it means the owner gave us the lock. */
+
+  if (oldstatus != 0) {
+    if (timedsuspend(self, abstime) == 0) {
+      if (!testandset(&p_wait_node->abandoned))
+	return 0; /* Timeout! */
+
+      /* Eat oustanding resume from owner, otherwise wait_node_free() below
+	 will race with owner's wait_node_dequeue(). */
+      suspend(self);
+    }
+  }
+
+  wait_node_free(p_wait_node);
+
+  READ_MEMORY_BARRIER();
+
+  return 1; /* Got the lock! */
+}
+
+void __pthread_alt_unlock(struct _pthread_fastlock *lock)
+{
+  struct wait_node *p_node, **pp_node, *p_max_prio, **pp_max_prio;
+  struct wait_node ** const pp_head = (struct wait_node **) &lock->__status;
+  int maxprio;
+
+  WRITE_MEMORY_BARRIER();
+
+#if defined TEST_FOR_COMPARE_AND_SWAP
+  if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+  {
+    __pthread_acquire(&lock->__spinlock);
+  }
+#endif
+
+  while (1) {
+
+  /* If no threads are waiting for this lock, try to just
+     atomically release it. */
+#if defined TEST_FOR_COMPARE_AND_SWAP
+    if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+    {
+      if (lock->__status == 0 || lock->__status == 1) {
+	lock->__status = 0;
+	break;
+      }
+    }
+#endif
+
+#if defined TEST_FOR_COMPARE_AND_SWAP
+    else
+#endif
+
+#if defined HAS_COMPARE_AND_SWAP
+    {
+      long oldstatus = lock->__status;
+      if (oldstatus == 0 || oldstatus == 1) {
+	if (__compare_and_swap_with_release_semantics (&lock->__status, oldstatus, 0))
+	  break;
+	else
+	  continue;
+      }
+    }
+#endif
+
+    /* Process the entire queue of wait nodes. Remove all abandoned
+       wait nodes and put them into the global free queue, and
+       remember the one unabandoned node which refers to the thread
+       having the highest priority. */
+
+    pp_max_prio = pp_node = pp_head;
+    p_max_prio = p_node = *pp_head;
+    maxprio = INT_MIN;
+
+    READ_MEMORY_BARRIER(); /* Prevent access to stale data through p_node */
+
+    while (p_node != (struct wait_node *) 1) {
+      int prio;
+
+      if (p_node->abandoned) {
+	/* Remove abandoned node. */
+#if defined TEST_FOR_COMPARE_AND_SWAP
+	if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+	  *pp_node = p_node->next;
+#endif
+#if defined TEST_FOR_COMPARE_AND_SWAP
+	else
+#endif
+#if defined HAS_COMPARE_AND_SWAP
+	  wait_node_dequeue(pp_head, pp_node, p_node);
+#endif
+	wait_node_free(p_node);
+	/* Note that the next assignment may take us to the beginning
+	   of the queue, to newly inserted nodes, if pp_node == pp_head.
+	   In that case we need a memory barrier to stabilize the first of
+	   these new nodes. */
+	p_node = *pp_node;
+	if (pp_node == pp_head)
+	  READ_MEMORY_BARRIER(); /* No stale reads through p_node */
+	continue;
+      } else if ((prio = p_node->thr->p_priority) >= maxprio) {
+	/* Otherwise remember it if its thread has a higher or equal priority
+	   compared to that of any node seen thus far. */
+	maxprio = prio;
+	pp_max_prio = pp_node;
+	p_max_prio = p_node;
+      }
+
+      /* This canno6 jump backward in the list, so no further read
+         barrier is needed. */
+      pp_node = &p_node->next;
+      p_node = *pp_node;
+    }
+
+    /* If all threads abandoned, go back to top */
+    if (maxprio == INT_MIN)
+      continue;
+
+    /* Now we want to to remove the max priority thread's wait node from
+       the list. Before we can do this, we must atomically try to change the
+       node's abandon state from zero to nonzero. If we succeed, that means we
+       have the node that we will wake up. If we failed, then it means the
+       thread timed out and abandoned the node in which case we repeat the
+       whole unlock operation. */
+
+    if (!testandset(&p_max_prio->abandoned)) {
+#if defined TEST_FOR_COMPARE_AND_SWAP
+      if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+	*pp_max_prio = p_max_prio->next;
+#endif
+#if defined TEST_FOR_COMPARE_AND_SWAP
+      else
+#endif
+#if defined HAS_COMPARE_AND_SWAP
+	wait_node_dequeue(pp_head, pp_max_prio, p_max_prio);
+#endif
+      restart(p_max_prio->thr);
+      break;
+    }
+  }
+
+#if defined TEST_FOR_COMPARE_AND_SWAP
+  if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+  {
+    __pthread_release(&lock->__spinlock);
+  }
+#endif
+}
+
+
+/* Compare-and-swap emulation with a spinlock */
+
+#ifdef TEST_FOR_COMPARE_AND_SWAP
+int __pthread_has_cas = 0;
+#endif
+
+#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)
+{
+  int res;
+
+  __pthread_acquire(spinlock);
+
+  if (*ptr == oldval) {
+    *ptr = newval; res = 1;
+  } else {
+    res = 0;
+  }
+
+  __pthread_release(spinlock);
+
+  return res;
+}
+
+#endif
+
+/* The retry strategy is as follows:
+   - We test and set the spinlock MAX_SPIN_COUNT times, calling
+     sched_yield() each time.  This gives ample opportunity for other
+     threads with priority >= our priority to make progress and
+     release the spinlock.
+   - If a thread with priority < our priority owns the spinlock,
+     calling sched_yield() repeatedly is useless, since we're preventing
+     the owning thread from making progress and releasing the spinlock.
+     So, after MAX_SPIN_LOCK attemps, we suspend the calling thread
+     using nanosleep().  This again should give time to the owning thread
+     for releasing the spinlock.
+     Notice that the nanosleep() interval must not be too small,
+     since the kernel does busy-waiting for short intervals in a realtime
+     process (!).  The smallest duration that guarantees thread
+     suspension is currently 2ms.
+   - When nanosleep() returns, we try again, doing MAX_SPIN_COUNT
+     sched_yield(), then sleeping again if needed. */
+
+static void __pthread_acquire(int * spinlock)
+{
+  int cnt = 0;
+  struct timespec tm;
+
+  READ_MEMORY_BARRIER();
+
+  while (testandset(spinlock)) {
+    if (cnt < MAX_SPIN_COUNT) {
+      sched_yield();
+      cnt++;
+    } else {
+      tm.tv_sec = 0;
+      tm.tv_nsec = SPIN_SLEEP_DURATION;
+      nanosleep(&tm, NULL);
+      cnt = 0;
+    }
+  }
+}

+ 218 - 0
libpthread/linuxthreads.old/spinlock.h

@@ -0,0 +1,218 @@
+/* Linuxthreads - a simple clone()-based implementation of Posix        */
+/* threads for Linux.                                                   */
+/* Copyright (C) 1998 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.                 */
+
+#include <bits/initspin.h>
+
+
+/* There are 2 compare and swap synchronization primitives with
+   different semantics:
+
+	1. compare_and_swap, which has acquire semantics (i.e. it
+	completes befor subsequent writes.)
+	2. compare_and_swap_with_release_semantics, which has release
+	semantics (it completes after previous writes.)
+
+   For those platforms on which they are the same. HAS_COMPARE_AND_SWAP
+   should be defined. For those platforms on which they are different,
+   HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS has to be defined.  */
+
+#ifndef HAS_COMPARE_AND_SWAP
+#ifdef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
+#define HAS_COMPARE_AND_SWAP
+#endif
+#endif
+
+#if defined(TEST_FOR_COMPARE_AND_SWAP)
+
+extern int __pthread_has_cas;
+extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval,
+                                      int * spinlock);
+
+static __inline__ int compare_and_swap(long * ptr, long oldval, long newval,
+                                   int * spinlock)
+{
+  if (__builtin_expect (__pthread_has_cas, 1))
+    return __compare_and_swap(ptr, oldval, newval);
+  else
+    return __pthread_compare_and_swap(ptr, oldval, newval, spinlock);
+}
+
+#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)
+{
+  return __compare_and_swap_with_release_semantics (ptr, oldval,
+						    newval);
+}
+
+#endif
+
+static __inline__ int compare_and_swap(long * ptr, long oldval, long newval,
+                                   int * spinlock)
+{
+  return __compare_and_swap(ptr, oldval, newval);
+}
+
+#else
+
+extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval,
+                                      int * spinlock);
+
+static __inline__ int compare_and_swap(long * ptr, long oldval, long newval,
+                                   int * spinlock)
+{
+  return __pthread_compare_and_swap(ptr, oldval, newval, spinlock);
+}
+
+#endif
+
+#ifndef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
+#define compare_and_swap_with_release_semantics compare_and_swap
+#define __compare_and_swap_with_release_semantics __compare_and_swap
+#endif
+
+/* Internal locks */
+
+extern void internal_function __pthread_lock(struct _pthread_fastlock * lock,
+					     pthread_descr self);
+extern int __pthread_unlock(struct _pthread_fastlock *lock);
+
+static __inline__ void __pthread_init_lock(struct _pthread_fastlock * lock)
+{
+  lock->__status = 0;
+  lock->__spinlock = __LT_SPINLOCK_INIT;
+}
+
+static __inline__ int __pthread_trylock (struct _pthread_fastlock * lock)
+{
+#if defined TEST_FOR_COMPARE_AND_SWAP
+  if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+  {
+    return (testandset(&lock->__spinlock) ? EBUSY : 0);
+  }
+#endif
+
+#if defined HAS_COMPARE_AND_SWAP
+  do {
+    if (lock->__status != 0) return EBUSY;
+  } while(! __compare_and_swap(&lock->__status, 0, 1));
+  return 0;
+#endif
+}
+
+/* Variation of internal lock used for pthread_mutex_t, supporting
+   timed-out waits.  Warning: do not mix these operations with the above ones
+   over the same lock object! */
+
+extern void __pthread_alt_lock(struct _pthread_fastlock * lock,
+			       pthread_descr self);
+
+extern int __pthread_alt_timedlock(struct _pthread_fastlock * lock,
+			       pthread_descr self, const struct timespec *abstime);
+
+extern void __pthread_alt_unlock(struct _pthread_fastlock *lock);
+
+static __inline__ void __pthread_alt_init_lock(struct _pthread_fastlock * lock)
+{
+  lock->__status = 0;
+  lock->__spinlock = __LT_SPINLOCK_INIT;
+}
+
+static __inline__ int __pthread_alt_trylock (struct _pthread_fastlock * lock)
+{
+#if defined TEST_FOR_COMPARE_AND_SWAP
+  if (!__pthread_has_cas)
+#endif
+#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
+  {
+    int res = EBUSY;
+
+    if (testandset(&lock->__spinlock) == 0)
+      {
+	if (lock->__status == 0)
+	  {
+	    lock->__status = 1;
+	    WRITE_MEMORY_BARRIER();
+	    res = 0;
+	  }
+	lock->__spinlock = __LT_SPINLOCK_INIT;
+      }
+    return res;
+  }
+#endif
+
+#if defined HAS_COMPARE_AND_SWAP
+  do {
+    if (lock->__status != 0) return EBUSY;
+  } while(! compare_and_swap(&lock->__status, 0, 1, &lock->__spinlock));
+  return 0;
+#endif
+}
+
+/* Operations on pthread_atomic, which is defined in internals.h */
+
+static __inline__ long atomic_increment(struct pthread_atomic *pa)
+{
+    long oldval;
+
+    do {
+	oldval = pa->p_count;
+    } while (!compare_and_swap(&pa->p_count, oldval, oldval + 1, &pa->p_spinlock));
+
+    return oldval;
+}
+
+
+static __inline__ long atomic_decrement(struct pthread_atomic *pa)
+{
+    long oldval;
+
+    do {
+	oldval = pa->p_count;
+    } while (!compare_and_swap(&pa->p_count, oldval, oldval - 1, &pa->p_spinlock));
+
+    return oldval;
+}
+
+
+static __inline__ void
+__pthread_set_own_extricate_if (pthread_descr self, pthread_extricate_if *peif)
+{
+  /* Only store a non-null peif if the thread has cancellation enabled.
+     Otherwise pthread_cancel will unconditionally call the extricate handler,
+     and restart the thread giving rise to forbidden spurious wakeups. */
+  if (peif == NULL
+      || THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)
+    {
+      /* If we are removing the extricate interface, we need to synchronize
+	 against pthread_cancel so that it does not continue with a pointer
+         to a deallocated pthread_extricate_if struct! The thread lock
+         is (ab)used for this synchronization purpose. */
+      if (peif == NULL)
+	__pthread_lock (THREAD_GETMEM(self, p_lock), self);
+      THREAD_SETMEM(self, p_extricate, peif);
+      if (peif == NULL)
+	__pthread_unlock (THREAD_GETMEM(self, p_lock));
+    }
+}

+ 126 - 0
libpthread/linuxthreads.old/sysdeps/alpha/pt-machine.h

@@ -0,0 +1,126 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   Alpha version.
+   Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson <rth@tamu.edu>.
+
+   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; see the file COPYING.LIB.  If not,
+   see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#include <features.h>
+
+#ifndef PT_EI
+# define PT_EI __extern_always_inline
+#endif
+
+#ifdef __linux__
+# include <asm/pal.h>
+#else
+# include <machine/pal.h>
+#endif
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  stack_pointer
+register char *stack_pointer __asm__("$30");
+
+
+/* Memory barrier; default is to do nothing */
+#define MEMORY_BARRIER() __asm__ __volatile__("mb" : : : "memory")
+/* Write barrier.  */
+#define WRITE_MEMORY_BARRIER() __asm__ __volatile__("wmb" : : : "memory")
+
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  long int ret, temp;
+
+  __asm__ __volatile__(
+	"/* Inline spinlock test & set */\n"
+	"1:\t"
+	"ldl_l %0,%3\n\t"
+	"bne %0,2f\n\t"
+	"or $31,1,%1\n\t"
+	"stl_c %1,%2\n\t"
+	"beq %1,1b\n"
+	"2:\tmb\n"
+	"/* End spinlock test & set */"
+	: "=&r"(ret), "=&r"(temp), "=m"(*spinlock)
+	: "m"(*spinlock)
+        : "memory");
+
+  return ret;
+}
+
+
+/* Begin allocating thread stacks at this address.  Default is to allocate
+   them just below the initial program stack.  */
+#define THREAD_STACK_START_ADDRESS  0x40000000000
+
+
+/* Return the thread descriptor for the current thread.  */
+#define THREAD_SELF \
+({									      \
+  register pthread_descr __self __asm__("$0");				      \
+  __asm__ ("call_pal %1" : "=r"(__self) : "i"(PAL_rduniq));		      \
+  __self;								      \
+})
+
+/* Initialize the thread-unique value.  */
+#define INIT_THREAD_SELF(descr, nr) \
+{									      \
+  register pthread_descr __self __asm__("$16") = (descr);		      \
+  __asm__ __volatile__ ("call_pal %1" : : "r"(__self), "i"(PAL_wruniq));      \
+}
+
+
+/* Compare-and-swap for semaphores. */
+
+#define HAS_COMPARE_AND_SWAP
+PT_EI int
+__compare_and_swap (long int *p, long int oldval, long int newval)
+{
+  long int ret;
+
+  __asm__ __volatile__ (
+	"/* Inline compare & swap */\n"
+	"1:\t"
+	"ldq_l %0,%4\n\t"
+	"cmpeq %0,%2,%0\n\t"
+	"beq %0,2f\n\t"
+	"mov %3,%0\n\t"
+	"stq_c %0,%1\n\t"
+	"beq %0,1b\n\t"
+	"2:\tmb\n"
+	"/* End compare & swap */"
+	: "=&r"(ret), "=m"(*p)
+	: "r"(oldval), "r"(newval), "m"(*p)
+        : "memory");
+
+  return ret;
+}
+
+/* We want the OS to assign stack addresses.  */
+#define FLOATING_STACKS 1
+
+/* Maximum size of the stack if the rlimit is unlimited.  */
+#define ARCH_STACK_MAX_SIZE     32*1024*1024
+
+#endif /* pt-machine.h */

+ 0 - 0
libpthread/linuxthreads/sysdeps/arc/pt-machine.h → libpthread/linuxthreads.old/sysdeps/arc/pt-machine.h


+ 110 - 0
libpthread/linuxthreads.old/sysdeps/arm/pt-machine.h

@@ -0,0 +1,110 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   ARM version.
+   Copyright (C) 1997, 1998, 2000, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Philip Blundell <philb@gnu.org>.
+
+   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; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#ifndef PT_EI
+# define PT_EI __extern_always_inline
+#endif
+
+#if defined(__thumb__)
+#if defined(__USE_LDREXSTREX__)
+PT_EI long int ldrex(int *spinlock)
+{
+	long int ret;
+	__asm__ __volatile__(
+		"ldrex %0, [%1]\n"
+		: "=r"(ret)
+		: "r"(spinlock) : "memory");
+	return ret;
+}
+
+PT_EI long int strex(int val, int *spinlock)
+{
+	long int ret;
+	__asm__ __volatile__(
+		"strex %0, %1, [%2]\n"
+		: "=r"(ret)
+		: "r" (val), "r"(spinlock) : "memory");
+	return ret;
+}
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  register unsigned int ret;
+
+  do {
+	  ret = ldrex(spinlock);
+  } while (strex(1, spinlock));
+
+  return ret;
+}
+
+#else /* __USE_LDREXSTREX__ */
+
+/* This will not work on ARM1 or ARM2 because SWP is lacking on those
+   machines.  Unfortunately we have no way to detect this at compile
+   time; let's hope nobody tries to use one.  */
+
+/* Spinlock implementation; required.  */
+PT_EI long int testandset (int *spinlock);
+PT_EI long int testandset (int *spinlock)
+{
+  register unsigned int ret;
+  void *pc;
+  __asm__ __volatile__(
+	".align 0\n"
+	"\tbx pc\n"
+	"\tnop\n"
+	"\t.arm\n"
+	"\tswp %0, %2, [%3]\n"
+	"\torr %1, pc, #1\n"
+	"\tbx %1\n"
+	"\t.force_thumb"
+	: "=r"(ret), "=r"(pc)
+	: "0"(1), "r"(spinlock));
+  return ret;
+}
+#endif
+#else /* __thumb__ */
+
+PT_EI long int testandset (int *spinlock);
+PT_EI long int testandset (int *spinlock)
+{
+  register unsigned int ret;
+  __asm__ __volatile__("swp %0, %1, [%2]"
+		       : "=r"(ret)
+		       : "0"(1), "r"(spinlock));
+  return ret;
+}
+#endif
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  stack_pointer
+register char * stack_pointer __asm__ ("sp");
+
+#endif /* pt-machine.h */

+ 73 - 0
libpthread/linuxthreads.old/sysdeps/avr32/pt-machine.h

@@ -0,0 +1,73 @@
+/* Machine-dependent pthreads configuration and inline functions.
+ *
+ * Copyright (C) 2005-2007 Atmel Corporation
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License.  See the file "COPYING.LIB" in the main directory of this
+ * archive for more details.
+ */
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#include <features.h>
+
+#ifndef PT_EI
+# define PT_EI __extern_always_inline
+#endif
+
+static __inline__ int
+_test_and_set (int *p, int v)
+{
+	int result;
+
+	__asm__ __volatile__(
+		"/* Inline test and set */\n"
+		"	xchg	%[old], %[mem], %[new]"
+		: [old] "=&r"(result)
+		: [mem] "r"(p), [new] "r"(v)
+		: "memory");
+
+	return result;
+}
+
+extern long int testandset (int *spinlock);
+extern int __compare_and_swap (long int *p, long int oldval, long int newval);
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+	return _test_and_set(spinlock, 1);
+}
+
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  stack_pointer
+register char * stack_pointer __asm__ ("sp");
+
+/* Compare-and-swap for semaphores. */
+
+#define HAS_COMPARE_AND_SWAP
+PT_EI int
+__compare_and_swap(long int *p, long int oldval, long int newval)
+{
+	long int result;
+
+	__asm__ __volatile__(
+		"/* Inline compare and swap */\n"
+		"1:	ssrf	5\n"
+		"	ld.w	%[result], %[mem]\n"
+		"	eor	%[result], %[old]\n"
+		"	brne	2f\n"
+		"	stcond	%[mem], %[new]\n"
+		"	brne	1b\n"
+		"2:"
+		: [result] "=&r"(result), [mem] "=m"(*p)
+		: "m"(*p), [new] "r"(newval), [old] "r"(oldval)
+		: "cc", "memory");
+
+	return result == 0;
+}
+
+#endif /* pt-machine.h */

+ 0 - 0
libpthread/linuxthreads/sysdeps/bfin/pt-machine.h → libpthread/linuxthreads.old/sysdeps/bfin/pt-machine.h


+ 0 - 0
libpthread/linuxthreads/sysdeps/c6x/pt-machine.h → libpthread/linuxthreads.old/sysdeps/c6x/pt-machine.h


+ 69 - 0
libpthread/linuxthreads.old/sysdeps/cris/pt-machine.h

@@ -0,0 +1,69 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   CRIS version.
+   Copyright (C) 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.
+
+   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,
+   see <http://www.gnu.org/licenses/>.  */
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#include <features.h>
+
+#ifndef PT_EI
+# define PT_EI __extern_always_inline
+#endif
+
+PT_EI long int
+testandset (int *spinlock)
+{
+  register unsigned long 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.  */
+
+#ifdef __arch_v32
+  __asm__ __volatile__("clearf p\n"
+		       "0:\n\t"
+		       "movu.b [%2],%0\n\t"
+		       "ax\n\t"
+		       "move.b %3,[%2]\n\t"
+		       "bcs 0b\n\t"
+		       "clearf p"
+		       : "=&r" (ret), "=m" (*spinlock)
+		       : "r" (spinlock), "r" ((int) 1), "m" (*spinlock)
+		       : "memory");
+#else  /* not __arch_v32 */
+  __asm__ __volatile__("clearf\n"
+		       "0:\n\t"
+		       "movu.b [%2],%0\n\t"
+		       "ax\n\t"
+		       "move.b %3,[%2]\n\t"
+		       "bwf 0b\n\t"
+		       "clearf"
+		       : "=&r" (ret), "=m" (*spinlock)
+		       : "r" (spinlock), "r" ((int) 1), "m" (*spinlock)
+		       : "memory");
+#endif /* __arch_v32 */
+  return ret;
+}
+
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.
+   I don't trust register variables, so let's do this the safe way.  */
+#define CURRENT_STACK_FRAME \
+ ({ char *sp; __asm__ ("move.d $sp,%0" : "=rm" (sp)); sp; })
+
+#endif /* pt-machine.h */

+ 0 - 0
libpthread/linuxthreads/sysdeps/frv/pt-machine.h → libpthread/linuxthreads.old/sysdeps/frv/pt-machine.h


+ 0 - 0
libpthread/linuxthreads/sysdeps/h8300/pt-machine.h → libpthread/linuxthreads.old/sysdeps/h8300/pt-machine.h


+ 146 - 0
libpthread/linuxthreads.old/sysdeps/i386/pt-machine.h

@@ -0,0 +1,146 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   i386 version.
+   Copyright (C) 1996-2001, 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson <rth@tamu.edu>.
+
+   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; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H	1
+
+#include <features.h>
+
+#ifndef __ASSEMBLER__
+#ifndef PT_EI
+# define PT_EI __extern_always_inline __attribute__((visibility("hidden")))
+#endif
+
+extern long int testandset (int *spinlock);
+extern int __compare_and_swap (long int *p, long int oldval, long int newval);
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  __builtin_frame_address (0)
+
+
+/* See if we can optimize for newer cpus... */
+#if defined __GNUC__ && __GNUC__ >= 2 && \
+   (defined __i486__ || defined __pentium__ || defined __pentiumpro__ || defined __pentium4__ || \
+    defined __athlon__ || defined __k8__)
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  long int ret;
+
+  __asm__ __volatile__ (
+	"xchgl %0, %1"
+	: "=r" (ret), "=m" (*spinlock)
+	: "0" (1), "m" (*spinlock)
+	: "memory");
+
+  return ret;
+}
+
+/* Compare-and-swap for semaphores.  It's always available on i686.  */
+#define HAS_COMPARE_AND_SWAP
+
+PT_EI int
+__compare_and_swap (long int *p, long int oldval, long int newval)
+{
+  char ret;
+  long int readval;
+
+  __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
+			: "=q" (ret), "=m" (*p), "=a" (readval)
+			: "r" (newval), "m" (*p), "a" (oldval)
+			: "memory");
+  return ret;
+}
+
+#if defined(__ASSUME_LDT_WORKS) && __ASSUME_LDT_WORKS > 0
+#include "useldt.h"
+#endif
+
+/* The P4 and above really want some help to prevent overheating.  */
+#define BUSY_WAIT_NOP	__asm__ ("rep; nop")
+
+
+#else /* Generic i386 implementation */
+
+extern int compare_and_swap_is_available (void);
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  long int ret;
+
+  __asm__ __volatile__(
+       "xchgl %0, %1"
+       : "=r"(ret), "=m"(*spinlock)
+       : "0"(1), "m"(*spinlock)
+       : "memory");
+
+  return ret;
+}
+
+
+/* Compare-and-swap for semaphores.
+   Available on the 486 and above, but not on the 386.
+   We test dynamically whether it's available or not. */
+
+#define HAS_COMPARE_AND_SWAP
+#define TEST_FOR_COMPARE_AND_SWAP
+
+PT_EI int
+__compare_and_swap (long int *p, long int oldval, long int newval)
+{
+  char ret;
+  long int readval;
+
+  __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
+			: "=q" (ret), "=m" (*p), "=a" (readval)
+			: "r" (newval), "m" (*p), "a" (oldval)
+			: "memory");
+  return ret;
+}
+
+PT_EI int
+compare_and_swap_is_available (void)
+{
+  int changed;
+  int oldflags;
+  /* get EFLAGS */
+  __asm__ __volatile__ ("pushfl; popl %0" : "=r" (oldflags) : );
+  /* Flip AC bit in EFLAGS.  */
+  __asm__ __volatile__ ("pushl %0; popfl" : : "r" (oldflags ^ 0x40000) : "cc");
+  /* reread EFLAGS */
+  __asm__ __volatile__ ("pushfl; popl %0" : "=r" (changed) : );
+  /* See if bit changed.  */
+  changed = (changed ^ oldflags) & 0x40000;
+  /* Restore EFLAGS.  */
+  __asm__ __volatile__ ("pushl %0; popfl" : : "r" (oldflags) : "cc");
+  /* If the AC flag did not change, it's a 386 and it lacks cmpxchg.
+     Otherwise, it's a 486 or above and it has cmpxchg.  */
+  return changed != 0;
+}
+#endif /* Generic i386 implementation */
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* pt-machine.h */

+ 184 - 0
libpthread/linuxthreads.old/sysdeps/i386/tls.h

@@ -0,0 +1,184 @@
+/* Definition for thread-local data handling.  linuxthreads/i386 version.
+   Copyright (C) 2002, 2003, 2004, 2005 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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _TLS_H
+#define _TLS_H
+
+# include <pt-machine.h>
+
+#ifndef __ASSEMBLER__
+# include <stdbool.h>
+# include <stddef.h>
+# include <stdint.h>
+
+/* Type for the dtv.  */
+typedef union dtv
+{
+  size_t counter;
+  void *pointer;
+} dtv_t;
+
+
+typedef struct
+{
+  void *tcb;		/* Pointer to the TCB.  Not necessary the
+			   thread descriptor used by libpthread.  */
+  dtv_t *dtv;
+  void *self;		/* Pointer to the thread descriptor.  */
+} tcbhead_t;
+#endif
+
+
+/* We can support TLS only if the floating-stack support is available.  */
+#if defined FLOATING_STACKS && defined HAVE_TLS_SUPPORT
+
+/* Signal that TLS support is available.  */
+//# define USE_TLS	1
+
+# ifndef __ASSEMBLER__
+/* Get system call information.  */
+#  include <sysdep.h>
+
+
+/* Get the thread descriptor definition.  */
+#  include <linuxthreads/descr.h>
+
+/* This is the size of the initial TCB.  */
+#  define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
+
+/* Alignment requirements for the initial TCB.  */
+#  define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
+
+/* This is the size of the TCB.  */
+#  define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct)
+
+/* Alignment requirements for the TCB.  */
+#  define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
+
+/* The TCB can have any size and the memory following the address the
+   thread pointer points to is unspecified.  Allocate the TCB there.  */
+#  define TLS_TCB_AT_TP	1
+
+
+/* Install the dtv pointer.  The pointer passed is to the element with
+   index -1 which contain the length.  */
+#  define INSTALL_DTV(descr, dtvp) \
+  ((tcbhead_t *) (descr))->dtv = (dtvp) + 1
+
+/* Install new dtv for current thread.  */
+#  define INSTALL_NEW_DTV(dtv) \
+  ({ struct _pthread_descr_struct *__descr;				      \
+     THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); })
+
+/* Return dtv of given thread descriptor.  */
+#  define GET_DTV(descr) \
+  (((tcbhead_t *) (descr))->dtv)
+
+#  ifdef __PIC__
+#   define TLS_EBX_ARG "r"
+#   define TLS_LOAD_EBX "xchgl %3, %%ebx\n\t"
+#  else
+#   define TLS_EBX_ARG "b"
+#   define TLS_LOAD_EBX
+#  endif
+
+#  define TLS_DO_MODIFY_LDT(descr, nr)					      \
+({									      \
+  struct modify_ldt_ldt_s ldt_entry =					      \
+    { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */,	      \
+      1, 0, 0, 1, 0, 1, 0 };						      \
+  int result;								      \
+  __asm__ __volatile__ (TLS_LOAD_EBX						      \
+		"int $0x80\n\t"						      \
+		TLS_LOAD_EBX						      \
+		: "=a" (result)						      \
+		: "0" (__NR_modify_ldt),				      \
+		/* The extra argument with the "m" constraint is necessary    \
+		   to let the compiler know that we are accessing LDT_ENTRY   \
+		   here.  */						      \
+		"m" (ldt_entry), TLS_EBX_ARG (1), "c" (&ldt_entry),	      \
+		"d" (sizeof (ldt_entry)));				      \
+  __builtin_expect (result, 0) != 0 ? -1 : nr * 8 + 7;			      \
+})
+
+#  define TLS_DO_SET_THREAD_AREA(descr, secondcall)			      \
+({									      \
+  struct modify_ldt_ldt_s ldt_entry =					      \
+    { -1, (unsigned long int) (descr), 0xfffff /* 4GB in pages */,	      \
+      1, 0, 0, 1, 0, 1, 0 };						      \
+  int result;								      \
+  if (secondcall)							      \
+    ldt_entry.entry_number = ({ int _gs;				      \
+				__asm__ ("movw %%gs, %w0" : "=q" (_gs));	      \
+				(_gs & 0xffff) >> 3; });		      \
+  __asm__ __volatile__ (TLS_LOAD_EBX						      \
+		"int $0x80\n\t"						      \
+		TLS_LOAD_EBX						      \
+		: "=a" (result), "=m" (ldt_entry.entry_number)		      \
+		: "0" (__NR_set_thread_area),				      \
+		/* The extra argument with the "m" constraint is necessary    \
+		   to let the compiler know that we are accessing LDT_ENTRY   \
+		   here.  */						      \
+		TLS_EBX_ARG (&ldt_entry), "m" (ldt_entry));		      \
+    __builtin_expect (result, 0) == 0 ? ldt_entry.entry_number * 8 + 3 : -1;  \
+})
+
+#  ifdef __ASSUME_SET_THREAD_AREA_SYSCALL
+#   define TLS_SETUP_GS_SEGMENT(descr, secondcall) \
+  TLS_DO_SET_THREAD_AREA (descr, firstcall)
+#  elif defined __NR_set_thread_area
+#   define TLS_SETUP_GS_SEGMENT(descr, secondcall) \
+  ({ int __seg = TLS_DO_SET_THREAD_AREA (descr, secondcall); \
+     __seg == -1 ? TLS_DO_MODIFY_LDT (descr, 0) : __seg; })
+#  else
+#   define TLS_SETUP_GS_SEGMENT(descr, secondcall) \
+  TLS_DO_MODIFY_LDT ((descr), 0)
+#  endif
+
+/* Code to initially initialize the thread pointer.  This might need
+   special attention since 'errno' is not yet available and if the
+   operation can cause a failure 'errno' must not be touched.  */
+#  define TLS_INIT_TP(descr, secondcall)				      \
+  ({									      \
+    void *_descr = (descr);						      \
+    tcbhead_t *head = _descr;						      \
+    int __gs;								      \
+									      \
+    head->tcb = _descr;							      \
+    /* For now the thread descriptor is at the same address.  */	      \
+    head->self = _descr;						      \
+									      \
+    __gs = TLS_SETUP_GS_SEGMENT (_descr, secondcall);			      \
+    if (__builtin_expect (__gs, 7) != -1)				      \
+      {									      \
+	__asm__ ("movw %w0, %%gs" : : "q" (__gs));				      \
+	__gs = 0;							      \
+      }									      \
+    __gs;								      \
+  })
+
+
+/* Return the address of the dtv for the current thread.  */
+#  define THREAD_DTV() \
+  ({ struct _pthread_descr_struct *__descr;				      \
+     THREAD_GETMEM (__descr, p_header.data.dtvp); })
+
+# endif	/* FLOATING_STACKS && HAVE_TLS_SUPPORT */
+#endif /* __ASSEMBLER__ */
+
+#endif	/* tls.h */

+ 306 - 0
libpthread/linuxthreads.old/sysdeps/i386/useldt.h

@@ -0,0 +1,306 @@
+/* Special definitions for ix86 machine using segment register based
+   thread descriptor.
+   Copyright (C) 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.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; see the file COPYING.LIB.  If not,
+   see <http://www.gnu.org/licenses/>.  */
+
+#ifndef __ASSEMBLER__
+#include <stddef.h>	/* For offsetof.  */
+#include <stdlib.h>	/* For abort().	 */
+
+
+/* We don't want to include the kernel header.	So duplicate the
+   information.	 */
+
+/* Structure passed on `modify_ldt' call.  */
+struct modify_ldt_ldt_s
+{
+  unsigned int entry_number;
+  unsigned long int base_addr;
+  unsigned int limit;
+  unsigned int seg_32bit:1;
+  unsigned int contents:2;
+  unsigned int read_exec_only:1;
+  unsigned int limit_in_pages:1;
+  unsigned int seg_not_present:1;
+  unsigned int useable:1;
+  unsigned int empty:25;
+};
+
+/* System call to set LDT entry.  */
+extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t);
+
+
+/* Return the thread descriptor for the current thread.
+
+   The contained asm must *not* be marked volatile since otherwise
+   assignments like
+	pthread_descr self = thread_self();
+   do not get optimized away.  */
+#define THREAD_SELF \
+({									      \
+  register pthread_descr __self;					      \
+  __asm__ ("movl %%gs:%c1,%0" : "=r" (__self)				      \
+	   : "i" (offsetof (struct _pthread_descr_struct,		      \
+			    p_header.data.self)));			      \
+  __self;								      \
+})
+
+
+/* Initialize the thread-unique value.	Two possible ways to do it.  */
+
+#define DO_MODIFY_LDT(descr, nr)					      \
+({									      \
+  struct modify_ldt_ldt_s ldt_entry =					      \
+    { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */,	      \
+      1, 0, 0, 1, 0, 1, 0 };						      \
+  if (__modify_ldt (1, &ldt_entry, sizeof (ldt_entry)) != 0)		      \
+    abort ();								      \
+  __asm__ ("movw %w0, %%gs" : : "q" (nr * 8 + 7));				      \
+})
+
+#ifdef __PIC__
+# define USETLS_EBX_ARG "r"
+# define USETLS_LOAD_EBX "xchgl %3, %%ebx\n\t"
+#else
+# define USETLS_EBX_ARG "b"
+# define USETLS_LOAD_EBX
+#endif
+
+/* When using the new set_thread_area call, we don't need to change %gs
+   because we inherited the value set up in the main thread by TLS setup.
+   We need to extract that value and set up the same segment in this
+   thread.  */
+#if USE_TLS
+# define DO_SET_THREAD_AREA_REUSE(nr)	1
+#else
+/* Without TLS, we do the initialization of the main thread, where NR == 0.  */
+# define DO_SET_THREAD_AREA_REUSE(nr)	(!__builtin_constant_p (nr) || (nr))
+#endif
+#define DO_SET_THREAD_AREA(descr, nr) \
+({									      \
+  int __gs;								      \
+  if (DO_SET_THREAD_AREA_REUSE (nr))					      \
+    {									      \
+      __asm__ ("movw %%gs, %w0" : "=q" (__gs));				      \
+      struct modify_ldt_ldt_s ldt_entry =				      \
+	{ (__gs & 0xffff) >> 3,						      \
+	  (unsigned long int) (descr), 0xfffff /* 4GB in pages */,	      \
+	  1, 0, 0, 1, 0, 1, 0 };					      \
+									      \
+      int __result;							      \
+      __asm__ (USETLS_LOAD_EBX						      \
+	     "movl %2, %%eax\n\t"					      \
+	     "int $0x80\n\t"						      \
+	     USETLS_LOAD_EBX						      \
+	     : "&a" (__result)						      \
+	     : USETLS_EBX_ARG (&ldt_entry), "i" (__NR_set_thread_area));      \
+      if (__result == 0)						      \
+	__asm__ ("movw %w0, %%gs" :: "q" (__gs));				      \
+      else								      \
+	__gs = -1;							      \
+    }									      \
+  else									      \
+    {									      \
+      struct modify_ldt_ldt_s ldt_entry =				      \
+	{ -1,								      \
+	  (unsigned long int) (descr), 0xfffff /* 4GB in pages */,	      \
+	  1, 0, 0, 1, 0, 1, 0 };					      \
+      int __result;							      \
+      __asm__ (USETLS_LOAD_EBX						      \
+	     "movl %2, %%eax\n\t"					      \
+	     "int $0x80\n\t"						      \
+	     USETLS_LOAD_EBX						      \
+	     : "&a" (__result)						      \
+	     : USETLS_EBX_ARG (&ldt_entry), "i" (__NR_set_thread_area));      \
+      if (__result == 0)						      \
+	{								      \
+	  __gs = (ldt_entry.entry_number << 3) + 3;			      \
+	  __asm__ ("movw %w0, %%gs" : : "q" (__gs));			      \
+	}								      \
+      else								      \
+	__gs = -1;							      \
+    }									      \
+  __gs;									      \
+})
+
+#if defined __ASSUME_SET_THREAD_AREA_SYSCALL
+# define INIT_THREAD_SELF(descr, nr)	DO_SET_THREAD_AREA (descr, nr)
+#elif defined __NR_set_thread_area
+# define INIT_THREAD_SELF(descr, nr)					      \
+({									      \
+  if (__builtin_expect (__have_no_set_thread_area, 0)			      \
+      || (DO_SET_THREAD_AREA (descr, DO_SET_THREAD_AREA_REUSE (nr)) == -1     \
+	  && (__have_no_set_thread_area = 1)))				      \
+    DO_MODIFY_LDT (descr, nr);						      \
+})
+/* Defined in pspinlock.c.  */
+extern int __have_no_set_thread_area;
+#else
+# define INIT_THREAD_SELF(descr, nr)	DO_MODIFY_LDT (descr, nr)
+#endif
+
+/* Free resources associated with thread descriptor.  */
+#ifdef __ASSUME_SET_THREAD_AREA_SYSCALL
+#define FREE_THREAD(descr, nr) do { } while (0)
+#elif defined __NR_set_thread_area
+#define FREE_THREAD(descr, nr) \
+{									      \
+  int __gs;								      \
+  __asm__ __volatile__ ("movw %%gs, %w0" : "=q" (__gs));		      \
+  if (__builtin_expect (__gs & 4, 0))					      \
+    {									      \
+      struct modify_ldt_ldt_s ldt_entry =				      \
+	{ nr, 0, 0, 0, 0, 1, 0, 1, 0, 0 };				      \
+      __modify_ldt (1, &ldt_entry, sizeof (ldt_entry));			      \
+    }									      \
+}
+#else
+#define FREE_THREAD(descr, nr) \
+{									      \
+  struct modify_ldt_ldt_s ldt_entry =					      \
+    { nr, 0, 0, 0, 0, 1, 0, 1, 0, 0 };					      \
+  __modify_ldt (1, &ldt_entry, sizeof (ldt_entry));			      \
+}
+#endif
+
+/* Read member of the thread descriptor directly.  */
+#define THREAD_GETMEM(descr, member) \
+({									      \
+  __typeof__ (descr->member) __value;					      \
+  if (sizeof (__value) == 1)						      \
+    __asm__ __volatile__ ("movb %%gs:%P2,%b0"				      \
+			  : "=q" (__value)				      \
+			  : "0" (0),					      \
+			    "i" (offsetof (struct _pthread_descr_struct,      \
+					   member)));			      \
+  else if (sizeof (__value) == 4)					      \
+    __asm__ __volatile__ ("movl %%gs:%P1,%0"				      \
+			  : "=r" (__value)				      \
+			  : "i" (offsetof (struct _pthread_descr_struct,      \
+					   member)));			      \
+  else									      \
+    {									      \
+      if (sizeof (__value) != 8)					      \
+	/* There should not be any value with a size other than 1, 4 or 8.  */\
+	abort ();							      \
+									      \
+      __asm__ __volatile__ ("movl %%gs:%P1,%%eax\n\t"			      \
+			    "movl %%gs:%P2,%%edx"			      \
+			    : "=A" (__value)				      \
+			    : "i" (offsetof (struct _pthread_descr_struct,    \
+					     member)),			      \
+			      "i" (offsetof (struct _pthread_descr_struct,    \
+					     member) + 4));		      \
+    }									      \
+  __value;								      \
+})
+
+/* Same as THREAD_GETMEM, but the member offset can be non-constant.  */
+#define THREAD_GETMEM_NC(descr, member) \
+({									      \
+  __typeof__ (descr->member) __value;					      \
+  if (sizeof (__value) == 1)						      \
+    __asm__ __volatile__ ("movb %%gs:(%2),%b0"				      \
+			  : "=q" (__value)				      \
+			  : "0" (0),					      \
+			    "r" (offsetof (struct _pthread_descr_struct,      \
+					   member)));			      \
+  else if (sizeof (__value) == 4)					      \
+    __asm__ __volatile__ ("movl %%gs:(%1),%0"				      \
+			  : "=r" (__value)				      \
+			  : "r" (offsetof (struct _pthread_descr_struct,      \
+					   member)));			      \
+  else									      \
+    {									      \
+      if (sizeof (__value) != 8)					      \
+	/* There should not be any value with a size other than 1, 4 or 8.  */\
+	abort ();							      \
+									      \
+      __asm__ __volatile__ ("movl %%gs:(%1),%%eax\n\t"			      \
+			    "movl %%gs:4(%1),%%edx"			      \
+			    : "=&A" (__value)				      \
+			    : "r" (offsetof (struct _pthread_descr_struct,    \
+					     member)));			      \
+    }									      \
+  __value;								      \
+})
+
+/* Same as THREAD_SETMEM, but the member offset can be non-constant.  */
+#define THREAD_SETMEM(descr, member, value) \
+({									      \
+  __typeof__ (descr->member) __value = (value);				      \
+  if (sizeof (__value) == 1)						      \
+    __asm__ __volatile__ ("movb %0,%%gs:%P1" :				      \
+			  : "q" (__value),				      \
+			    "i" (offsetof (struct _pthread_descr_struct,      \
+					   member)));			      \
+  else if (sizeof (__value) == 4)					      \
+    __asm__ __volatile__ ("movl %0,%%gs:%P1" :				      \
+			  : "r" (__value),				      \
+			    "i" (offsetof (struct _pthread_descr_struct,      \
+					   member)));			      \
+  else									      \
+    {									      \
+      if (sizeof (__value) != 8)					      \
+	/* There should not be any value with a size other than 1, 4 or 8.  */\
+	abort ();							      \
+									      \
+      __asm__ __volatile__ ("movl %%eax,%%gs:%P1\n\n"			      \
+			    "movl %%edx,%%gs:%P2" :			      \
+			    : "A" (__value),				      \
+			      "i" (offsetof (struct _pthread_descr_struct,    \
+					     member)),			      \
+			      "i" (offsetof (struct _pthread_descr_struct,    \
+					     member) + 4));		      \
+    }									      \
+})
+
+/* Set member of the thread descriptor directly.  */
+#define THREAD_SETMEM_NC(descr, member, value) \
+({									      \
+  __typeof__ (descr->member) __value = (value);				      \
+  if (sizeof (__value) == 1)						      \
+    __asm__ __volatile__ ("movb %0,%%gs:(%1)" :				      \
+			  : "q" (__value),				      \
+			    "r" (offsetof (struct _pthread_descr_struct,      \
+					   member)));			      \
+  else if (sizeof (__value) == 4)					      \
+    __asm__ __volatile__ ("movl %0,%%gs:(%1)" :				      \
+			  : "r" (__value),				      \
+			    "r" (offsetof (struct _pthread_descr_struct,      \
+					   member)));			      \
+  else									      \
+    {									      \
+      if (sizeof (__value) != 8)					      \
+	/* There should not be any value with a size other than 1, 4 or 8.  */\
+	abort ();							      \
+									      \
+      __asm__ __volatile__ ("movl %%eax,%%gs:(%1)\n\t"			      \
+			    "movl %%edx,%%gs:4(%1)" :			      \
+			    : "A" (__value),				      \
+			      "r" (offsetof (struct _pthread_descr_struct,    \
+					     member)));			      \
+    }									      \
+})
+#endif
+
+/* We want the OS to assign stack addresses.  */
+#define FLOATING_STACKS	1
+
+/* Maximum size of the stack if the rlimit is unlimited.  */
+#define ARCH_STACK_MAX_SIZE	8*1024*1024

+ 134 - 0
libpthread/linuxthreads.old/sysdeps/ia64/pt-machine.h

@@ -0,0 +1,134 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   IA-64 version.
+   Copyright (C) 1999, 2000, 2002, 2003, 2004 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; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#include <features.h>
+#include <ia64intrin.h>
+
+#include <sys/types.h>
+extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base,
+                     size_t __child_stack_size, int __flags, void *__arg, ...);
+
+#ifndef PT_EI
+# define PT_EI __extern_always_inline
+#endif
+
+/* Make sure gcc doesn't try to be clever and move things around on
+   us. We need to use _exactly_ the address the user gave us, not some
+   alias that contains the same information.  */
+#define __atomic_fool_gcc(x) (*(volatile struct { int a[100]; } *)x)
+
+#ifndef ELF_MACHINE_NAME
+
+#define NEED_SEPARATE_REGISTER_STACK
+
+/* We want the OS to assign stack addresses.  */
+#define FLOATING_STACKS 1
+
+/* Maximum size of the stack if the rlimit is unlimited.  */
+#define ARCH_STACK_MAX_SIZE     32*1024*1024
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.
+   r12 (sp) is the stack pointer. */
+#define CURRENT_STACK_FRAME  stack_pointer
+register char *stack_pointer __asm__ ("sp");
+
+
+/* Register r13 (tp) is reserved by the ABI as "thread pointer". */
+struct _pthread_descr_struct;
+register struct _pthread_descr_struct *__thread_self __asm__("r13");
+
+/* Return the thread descriptor for the current thread.  */
+#define THREAD_SELF  __thread_self
+
+/* Initialize the thread-unique value.  */
+#define INIT_THREAD_SELF(descr, nr)  (__thread_self = (descr))
+
+
+/* Access to data in the thread descriptor is easy.  */
+#define THREAD_GETMEM(descr, member) \
+  ((void) sizeof (descr), THREAD_SELF->member)
+#define THREAD_GETMEM_NC(descr, member) \
+  ((void) sizeof (descr), THREAD_SELF->member)
+#define THREAD_SETMEM(descr, member, value) \
+  ((void) sizeof (descr), THREAD_SELF->member = (value))
+#define THREAD_SETMEM_NC(descr, member, value) \
+  ((void) sizeof (descr), THREAD_SELF->member = (value))
+
+
+/* Memory barrier */
+#define MEMORY_BARRIER() __sync_synchronize ()
+
+
+#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
+
+PT_EI int
+__compare_and_swap (long int *p, long int oldval, long int newval)
+{
+  long int readval;
+
+  __asm__ __volatile__
+       ("mov ar.ccv=%4;;\n\t"
+	"cmpxchg8.acq %0=%1,%2,ar.ccv"
+	: "=r" (readval), "=m" (__atomic_fool_gcc (p))
+	: "r"(newval), "m" (__atomic_fool_gcc (p)), "r" (oldval)
+	: "memory");
+  return readval == oldval;
+}
+
+PT_EI int
+__compare_and_swap_with_release_semantics (long int *p,
+					   long int oldval,
+					   long int newval)
+{
+  long int readval;
+
+  __asm__ __volatile__
+       ("mov ar.ccv=%4;;\n\t"
+	"cmpxchg8.rel %0=%1,%2,ar.ccv"
+	: "=r" (readval), "=m" (__atomic_fool_gcc (p))
+	: "r"(newval), "m" (__atomic_fool_gcc (p)), "r" (oldval)
+	: "memory");
+  return readval == oldval;
+}
+
+#endif /* ELF_MACHINE_NAME */
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  long int ret;
+
+  __asm__ __volatile__(
+       "xchg4 %0=%1,%2"
+       : "=r"(ret), "=m"(__atomic_fool_gcc (spinlock))
+       : "r"(1), "m"(__atomic_fool_gcc (spinlock))
+       : "memory");
+
+  return ret;
+}
+
+/* Indicate that we are looping.  */
+#define BUSY_WAIT_NOP	__asm__ ("hint @pause")
+
+#endif /* pt-machine.h */

+ 138 - 0
libpthread/linuxthreads.old/sysdeps/ia64/tls.h

@@ -0,0 +1,138 @@
+/* Definitions for thread-local data handling.  linuxthreads/IA-64 version.
+   Copyright (C) 2002, 2003, 2004, 2005 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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _TLS_H
+#define _TLS_H
+
+#ifndef __ASSEMBLER__
+
+# include <pt-machine.h>
+# include <stdbool.h>
+# include <stddef.h>
+
+/* Type for the dtv.  */
+typedef union dtv
+{
+  size_t counter;
+  struct
+  {
+    void *val;
+    bool is_static;
+  } pointer;
+} dtv_t;
+
+#else /* __ASSEMBLER__ */
+# include <tcb-offsets.h>
+#endif /* __ASSEMBLER__ */
+
+#ifdef HAVE_TLS_SUPPORT
+
+/* Signal that TLS support is available.  */
+# define USE_TLS        1
+
+# ifndef __ASSEMBLER__
+
+typedef struct
+{
+  dtv_t *dtv;
+  void *private;
+} tcbhead_t;
+
+/* This is the size of the initial TCB.  */
+#  define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
+
+/* Alignment requirements for the initial TCB.  */
+#  define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
+
+/* This is the size of the TCB.  */
+#  define TLS_TCB_SIZE sizeof (tcbhead_t)
+
+/* This is the size we need before TCB.  */
+#  define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct)
+
+/* Alignment requirements for the TCB.  */
+#  define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
+
+/* 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(tcbp, dtvp) \
+  ((tcbhead_t *) (tcbp))->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(tcbp) \
+  (((tcbhead_t *) (tcbp))->dtv)
+
+#if defined NEED_DL_SYSINFO
+# define INIT_SYSINFO \
+  (((tcbhead_t *) __thread_self)->private = (void *) GLRO(dl_sysinfo))
+#else
+# define INIT_SYSINFO 0
+#endif
+
+/* Code to initially initialize the thread pointer.  This might need
+   special attention since 'errno' is not yet available and if the
+   operation can cause a failure 'errno' must not be touched.  */
+#  define TLS_INIT_TP(tcbp, secondcall) \
+  (__thread_self = (__typeof (__thread_self)) (tcbp), INIT_SYSINFO, 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.  */
+#  undef THREAD_SELF
+#  define THREAD_SELF (__thread_self - 1)
+
+#  undef INIT_THREAD_SELF
+#  define INIT_THREAD_SELF(descr, nr) \
+  (__thread_self = (struct _pthread_descr_struct *)(descr) + 1)
+
+# define TLS_MULTIPLE_THREADS_IN_TCB 1
+
+# endif
+
+#else
+
+# ifndef __ASSEMBLER__
+
+typedef struct
+{
+  void *tcb;
+  dtv_t *dtv;
+  void *self;
+  int multiple_threads;
+} tcbhead_t;
+
+#  define NONTLS_INIT_TP \
+  do { 									\
+    static const tcbhead_t nontls_init_tp = { .multiple_threads = 0 };	\
+    __thread_self = (__typeof (__thread_self)) &nontls_init_tp;		\
+  } while (0)
+
+#endif
+
+#endif /* USE_TLS */
+
+#endif	/* tls.h */

+ 74 - 0
libpthread/linuxthreads.old/sysdeps/m68k/pt-machine.h

@@ -0,0 +1,74 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   m68k version.
+   Copyright (C) 1996, 1998, 2000, 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson <rth@tamu.edu>.
+
+   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; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#include <features.h>
+
+#ifndef PT_EI
+# define PT_EI __extern_always_inline
+#endif
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  char ret;
+
+  __asm__ __volatile__(
+#if !defined(__mcoldfire__) && !defined(__mcf5200__) && !defined(__m68000)
+         "tas %1; sne %0"
+#else
+         "bset #7,%1; sne %0"
+#endif
+       : "=&dm"(ret), "=m"(*spinlock)
+       : "m"(*spinlock)
+       : "cc");
+
+  return ret;
+}
+
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  stack_pointer
+register char * stack_pointer __asm__ ("%sp");
+
+
+/* Compare-and-swap for semaphores. */
+
+#if !defined(__mcoldfire__) && !defined(__mcf5200__) && !defined(__mc68000)
+#define HAS_COMPARE_AND_SWAP
+PT_EI int
+__compare_and_swap (long int *p, long int oldval, long int newval)
+{
+  char ret;
+  long int readval;
+
+  __asm__ __volatile__ ("casl %2, %3, %1; seq %0"
+			: "=dm" (ret), "=m" (*p), "=d" (readval)
+			: "d" (newval), "m" (*p), "2" (oldval));
+
+  return ret;
+}
+#endif
+
+#endif /* pt-machine.h */

+ 0 - 0
libpthread/linuxthreads/sysdeps/microblaze/pt-machine.h → libpthread/linuxthreads.old/sysdeps/microblaze/pt-machine.h


+ 0 - 0
libpthread/linuxthreads/sysdeps/microblaze/sigcontextinfo.h → libpthread/linuxthreads.old/sysdeps/microblaze/sigcontextinfo.h


+ 105 - 0
libpthread/linuxthreads.old/sysdeps/mips/pt-machine.h

@@ -0,0 +1,105 @@
+/* Machine-dependent pthreads configuration and inline functions.
+
+   Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003, 2004
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ralf Baechle <ralf@gnu.org>.
+   Based on the Alpha version by Richard Henderson <rth@tamu.edu>.
+
+   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; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#include <features.h>
+
+#ifndef PT_EI
+# define PT_EI __extern_always_inline
+#endif
+
+/* Copyright (C) 2000, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Maciej W. Rozycki <macro@ds2.pg.gda.pl>, 2000.  */
+static __inline__ int
+__NTH (_test_and_set (int *p, int v))
+{
+  int r, t;
+
+  __asm__ __volatile__
+    ("/* Inline test and set */\n"
+     "1:\n\t"
+     ".set	push\n\t"
+     ".set	mips2\n\t"
+     "ll	%0,%3\n\t"
+     "move	%1,%4\n\t"
+     "beq	%0,%4,2f\n\t"
+     "sc	%1,%2\n\t"
+     ".set	pop\n\t"
+     "beqz	%1,1b\n"
+     "2:\n\t"
+     "/* End test and set */"
+     : "=&r" (r), "=&r" (t), "=m" (*p)
+     : "m" (*p), "r" (v)
+     : "memory");
+
+  return r;
+}
+
+
+/* Spinlock implementation; required.  */
+
+PT_EI long int
+testandset (int *spinlock)
+{
+  return _test_and_set (spinlock, 1);
+}
+
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  stack_pointer
+register char * stack_pointer __asm__ ("$29");
+
+
+/* Compare-and-swap for semaphores. */
+
+#define HAS_COMPARE_AND_SWAP
+PT_EI int
+__compare_and_swap (long int *p, long int oldval, long int newval)
+{
+  long int ret, temp;
+
+  __asm__ __volatile__
+    ("/* Inline compare & swap */\n"
+     "1:\n\t"
+     ".set	push\n\t"
+     ".set	mips2\n\t"
+     "ll	%1,%5\n\t"
+     "move	%0,$0\n\t"
+     "bne	%1,%3,2f\n\t"
+     "move	%0,%4\n\t"
+     "sc	%0,%2\n\t"
+     ".set	pop\n\t"
+     "beqz	%0,1b\n"
+     "2:\n\t"
+     "/* End compare & swap */"
+     : "=&r" (ret), "=&r" (temp), "=m" (*p)
+     : "r" (oldval), "r" (newval), "m" (*p)
+     : "memory");
+
+  return ret;
+}
+
+#endif /* pt-machine.h */

+ 0 - 0
libpthread/linuxthreads/sysdeps/nios/pt-machine.h → libpthread/linuxthreads.old/sysdeps/nios/pt-machine.h


+ 0 - 0
libpthread/linuxthreads/sysdeps/nios2/pt-machine.h → libpthread/linuxthreads.old/sysdeps/nios2/pt-machine.h


+ 101 - 0
libpthread/linuxthreads.old/sysdeps/powerpc/pt-machine.h

@@ -0,0 +1,101 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   powerpc version.
+   Copyright (C) 1996, 1997, 1998, 2000, 2001, 2002 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; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/* These routines are from Appendix G of the 'PowerPC 601 RISC Microprocessor
+   User's Manual', by IBM and Motorola.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#include <features.h>
+
+#ifndef PT_EI
+# define PT_EI __extern_always_inline
+#endif
+
+/* For multiprocessor systems, we want to ensure all memory accesses
+   are completed before we reset a lock.  On other systems, we still
+   need to make sure that the compiler has flushed everything to memory.  */
+#define MEMORY_BARRIER() __asm__ __volatile__ ("sync" : : : "memory")
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  stack_pointer
+register char * stack_pointer __asm__ ("r1");
+
+/* Register r2 (tp) is reserved by the ABI as "thread pointer". */
+struct _pthread_descr_struct;
+register struct _pthread_descr_struct *__thread_self __asm__("r2");
+
+/* Return the thread descriptor for the current thread.  */
+#define THREAD_SELF  __thread_self
+
+/* Initialize the thread-unique value.  */
+#define INIT_THREAD_SELF(descr, nr)  (__thread_self = (descr))
+
+/* Compare-and-swap for semaphores. */
+/* 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
+
+PT_EI int
+__compare_and_swap (long int *p, long int oldval, long int newval)
+{
+  int ret;
+
+  __asm__ __volatile__ (
+	   "0:    lwarx %0,0,%1 ;"
+	   "      xor. %0,%3,%0;"
+	   "      bne 1f;"
+	   "      stwcx. %2,0,%1;"
+	   "      bne- 0b;"
+	   "1:    "
+	: "=&r"(ret)
+	: "r"(p), "r"(newval), "r"(oldval)
+	: "cr0", "memory");
+  /* This version of __compare_and_swap is to be used when acquiring
+     a lock, so we don't need to worry about whether other memory
+     operations have completed, but we do need to be sure that any loads
+     after this point really occur after we have acquired the lock.  */
+  __asm__ __volatile__ ("isync" : : : "memory");
+  return ret == 0;
+}
+
+PT_EI int
+__compare_and_swap_with_release_semantics (long int *p,
+					   long int oldval, long int newval)
+{
+  int ret;
+
+  MEMORY_BARRIER ();
+  __asm__ __volatile__ (
+	   "0:    lwarx %0,0,%1 ;"
+	   "      xor. %0,%3,%0;"
+	   "      bne 1f;"
+	   "      stwcx. %2,0,%1;"
+	   "      bne- 0b;"
+	   "1:    "
+	: "=&r"(ret)
+	: "r"(p), "r"(newval), "r"(oldval)
+	: "cr0", "memory");
+  return ret == 0;
+}
+
+#endif /* pt-machine.h */

+ 415 - 0
libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-lock.h

@@ -0,0 +1,415 @@
+/* libc-internal interface for mutex locks.  LinuxThreads version.
+   Copyright (C) 1996,1997,1998,1999,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.
+
+   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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _BITS_LIBC_LOCK_H
+#define _BITS_LIBC_LOCK_H 1
+
+#include <pthread.h>
+
+#if defined _LIBC && !defined NOT_IN_libc
+#include <linuxthreads.old/internals.h>
+#endif
+
+/* Mutex type.  */
+#if defined(_LIBC) || defined(_IO_MTSAFE_IO)
+typedef pthread_mutex_t __libc_lock_t;
+typedef pthread_mutex_t __libc_lock_recursive_t;
+# ifdef __USE_UNIX98
+typedef pthread_rwlock_t __libc_rwlock_t;
+# else
+typedef struct __libc_rwlock_opaque__ __libc_rwlock_t;
+# endif
+typedef __libc_lock_recursive_t __rtld_lock_recursive_t;
+#else
+typedef struct __libc_lock_opaque__ __libc_lock_t;
+typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
+typedef struct __libc_rwlock_opaque__ __libc_rwlock_t;
+#endif
+
+/* Type for key to thread-specific data.  */
+typedef pthread_key_t __libc_key_t;
+
+/* Define a lock variable NAME with storage class CLASS.  The lock must be
+   initialized with __libc_lock_init before it can be used (or define it
+   with __libc_lock_define_initialized, below).  Use `extern' for CLASS to
+   declare a lock defined in another module.  In public structure
+   definitions you must use a pointer to the lock structure (i.e., NAME
+   begins with a `*'), because its storage size will not be known outside
+   of libc.  */
+#define __libc_lock_define(CLASS,NAME) \
+  CLASS __libc_lock_t NAME;
+#define __libc_rwlock_define(CLASS,NAME) \
+  CLASS __libc_rwlock_t NAME;
+#define __libc_lock_define_recursive(CLASS,NAME) \
+  CLASS __libc_lock_recursive_t NAME;
+#define __rtld_lock_define_recursive(CLASS,NAME) \
+  CLASS __rtld_lock_recursive_t NAME;
+
+/* Define an initialized lock variable NAME with storage class CLASS.
+
+   For the C library we take a deeper look at the initializer.  For
+   this implementation all fields are initialized to zero.  Therefore
+   we don't initialize the variable which allows putting it into the
+   BSS section.  (Except on PA-RISC and other odd architectures, where
+   initialized locks must be set to one due to the lack of normal
+   atomic operations.) */
+
+#if __LT_SPINLOCK_INIT == 0
+#  define __libc_lock_define_initialized(CLASS,NAME) \
+  CLASS __libc_lock_t NAME;
+#else
+#  define __libc_lock_define_initialized(CLASS,NAME) \
+  CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+#define __libc_rwlock_define_initialized(CLASS,NAME) \
+  CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER;
+
+/* Define an initialized recursive lock variable NAME with storage
+   class CLASS.  */
+#define __libc_lock_define_initialized_recursive(CLASS,NAME) \
+  CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER;
+#define _LIBC_LOCK_RECURSIVE_INITIALIZER \
+  {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP}
+
+#define __rtld_lock_define_initialized_recursive(CLASS,NAME) \
+  CLASS __rtld_lock_recursive_t NAME = _RTLD_LOCK_RECURSIVE_INITIALIZER;
+#define _RTLD_LOCK_RECURSIVE_INITIALIZER \
+  {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP}
+
+#if defined _LIBC && defined IS_IN_libpthread
+# define __libc_maybe_call(FUNC, ARGS, ELSE) FUNC ARGS
+#else
+# if defined __PIC__ || (defined _LIBC && defined SHARED)
+#  define __libc_maybe_call(FUNC, ARGS, ELSE) \
+  (__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \
+                    _fn != NULL ? (*_fn) ARGS : ELSE; }))
+# else
+#  define __libc_maybe_call(FUNC, ARGS, ELSE) \
+  (FUNC != NULL ? FUNC ARGS : ELSE)
+# endif
+#endif
+#if defined _LIBC && !defined NOT_IN_libc && defined SHARED
+# define __libc_maybe_call2(FUNC, ARGS, ELSE) \
+  ({__builtin_expect (__libc_pthread_functions.ptr_##FUNC != NULL, 0) \
+    ? __libc_pthread_functions.ptr_##FUNC ARGS : ELSE; })
+#else
+# define __libc_maybe_call2(FUNC, ARGS, ELSE) __libc_maybe_call (__##FUNC, ARGS, ELSE)
+#endif
+
+/* Initialize the named lock variable, leaving it in a consistent, unlocked
+   state.  */
+#if defined _LIBC && !defined NOT_IN_libc && defined SHARED
+#define __libc_lock_init(NAME) \
+  ({									      \
+    (NAME).__m_count = 0;						      \
+    (NAME).__m_owner = NULL;						      \
+    (NAME).__m_kind = PTHREAD_MUTEX_TIMED_NP;				      \
+    (NAME).__m_lock.__status = 0;					      \
+    (NAME).__m_lock.__spinlock = __LT_SPINLOCK_INIT;			      \
+    0; })
+#else
+#define __libc_lock_init(NAME) \
+  (__libc_maybe_call2 (pthread_mutex_init, (&(NAME), NULL), 0))
+#endif
+#define __libc_rwlock_init(NAME) \
+  (__libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0));
+
+/* Same as last but this time we initialize an adaptive mutex.  */
+#if defined _LIBC && !defined NOT_IN_libc && defined SHARED
+#define __libc_lock_init_adaptive(NAME) \
+  ({									      \
+    (NAME).__m_count = 0;						      \
+    (NAME).__m_owner = NULL;						      \
+    (NAME).__m_kind = PTHREAD_MUTEX_ADAPTIVE_NP;			      \
+    (NAME).__m_lock.__status = 0;					      \
+    (NAME).__m_lock.__spinlock = __LT_SPINLOCK_INIT;			      \
+    0; })
+#else
+#define __libc_lock_init_adaptive(NAME) \
+  do {									      \
+    if (__pthread_mutex_init != NULL)					      \
+      {									      \
+	pthread_mutexattr_t __attr;					      \
+	__pthread_mutexattr_init (&__attr);				      \
+	__pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_ADAPTIVE_NP);     \
+	__pthread_mutex_init (&(NAME), &__attr);			      \
+	__pthread_mutexattr_destroy (&__attr);				      \
+      }									      \
+  } while (0);
+#endif
+
+/* Same as last but this time we initialize a recursive mutex.  */
+#if defined _LIBC && !defined NOT_IN_libc && defined SHARED
+#define __libc_lock_init_recursive(NAME) \
+  ({									      \
+    (NAME).__m_count = 0;						      \
+    (NAME).__m_owner = NULL;					      \
+    (NAME).__m_kind = PTHREAD_MUTEX_RECURSIVE_NP;			      \
+    (NAME).__m_lock.__status = 0;					      \
+    (NAME).__m_lock.__spinlock = __LT_SPINLOCK_INIT;		      \
+    0; })
+#else
+#define __libc_lock_init_recursive(NAME) \
+  do {									      \
+    if (__pthread_mutex_init != NULL)					      \
+      {									      \
+	pthread_mutexattr_t __attr;					      \
+	__pthread_mutexattr_init (&__attr);				      \
+	__pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \
+	__pthread_mutex_init (&(NAME), &__attr);			      \
+	__pthread_mutexattr_destroy (&__attr);				      \
+      }									      \
+  } while (0);
+#endif
+#define __rtld_lock_init_recursive(NAME) \
+  __libc_lock_init_recursive (NAME)
+
+/* Finalize the named lock variable, which must be locked.  It cannot be
+   used again until __libc_lock_init is called again on it.  This must be
+   called on a lock variable before the containing storage is reused.  */
+#define __libc_lock_fini(NAME) \
+  (__libc_maybe_call2 (pthread_mutex_destroy, (&(NAME)), 0));
+#define __libc_rwlock_fini(NAME) \
+  (__libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0));
+
+/* Finalize recursive named lock.  */
+#define __libc_lock_fini_recursive(NAME) __libc_lock_fini ((NAME).mutex)
+#define __rtld_lock_fini_recursive(NAME) __libc_lock_fini_recursive (NAME)
+
+/* Lock the named lock variable.  */
+#define __libc_lock_lock(NAME) \
+  (__libc_maybe_call2 (pthread_mutex_lock, (&(NAME)), 0));
+#define __libc_rwlock_rdlock(NAME) \
+  (__libc_maybe_call (__pthread_rwlock_rdlock, (&(NAME)), 0));
+#define __libc_rwlock_wrlock(NAME) \
+  (__libc_maybe_call (__pthread_rwlock_wrlock, (&(NAME)), 0));
+
+/* Lock the recursive named lock variable.  */
+#define __libc_lock_lock_recursive(NAME) __libc_lock_lock ((NAME).mutex)
+
+/* Try to lock the named lock variable.  */
+#define __libc_lock_trylock(NAME) \
+  (__libc_maybe_call2 (pthread_mutex_trylock, (&(NAME)), 0))
+#define __libc_rwlock_tryrdlock(NAME) \
+  (__libc_maybe_call (__pthread_rwlock_tryrdlock, (&(NAME)), 0))
+#define __libc_rwlock_trywrlock(NAME) \
+  (__libc_maybe_call (__pthread_rwlock_trywrlock, (&(NAME)), 0))
+
+/* Try to lock the recursive named lock variable.  */
+#define __libc_lock_trylock_recursive(NAME) __libc_lock_trylock ((NAME).mutex)
+#define __rtld_lock_trylock_recursive(NAME) \
+  __libc_lock_trylock_recursive (NAME)
+
+/* Unlock the named lock variable.  */
+#define __libc_lock_unlock(NAME) \
+  (__libc_maybe_call2 (pthread_mutex_unlock, (&(NAME)), 0));
+#define __libc_rwlock_unlock(NAME) \
+  (__libc_maybe_call (__pthread_rwlock_unlock, (&(NAME)), 0));
+
+/* Unlock the recursive named lock variable.  */
+#define __libc_lock_unlock_recursive(NAME) __libc_lock_unlock ((NAME).mutex)
+
+/* Define once control variable.  */
+#if PTHREAD_ONCE_INIT == 0
+/* Special case for static variables where we can avoid the initialization
+   if it is zero.  */
+# define __libc_once_define(CLASS, NAME) \
+  CLASS pthread_once_t NAME
+#else
+# define __libc_once_define(CLASS, NAME) \
+  CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT
+#endif
+
+/* Call handler iff the first call.  */
+#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
+  do {									      \
+    if (__pthread_once != NULL)						      \
+      __pthread_once (&(ONCE_CONTROL), (INIT_FUNCTION));		      \
+    else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) {			      \
+      INIT_FUNCTION ();							      \
+      (ONCE_CONTROL) = !PTHREAD_ONCE_INIT;				      \
+    }									      \
+  } while (0)
+
+
+/* Start critical region with cleanup.  */
+#define __libc_cleanup_region_start(DOIT, FCT, ARG) \
+  { struct _pthread_cleanup_buffer _buffer;				      \
+    int _avail = (DOIT) && _pthread_cleanup_push_defer != NULL;		      \
+    if (_avail) {							      \
+      _pthread_cleanup_push_defer (&_buffer, (FCT), (ARG));		      \
+    }
+
+/* End critical region with cleanup.  */
+#define __libc_cleanup_region_end(DOIT) \
+    if (_avail) {							      \
+      _pthread_cleanup_pop_restore (&_buffer, (DOIT));			      \
+    }									      \
+  }
+
+/* Sometimes we have to exit the block in the middle.  */
+#define __libc_cleanup_end(DOIT) \
+    if (_avail) {							      \
+      _pthread_cleanup_pop_restore (&_buffer, (DOIT));			      \
+    }
+
+#if 0
+#define __libc_cleanup_push(fct, arg) \
+    { struct _pthread_cleanup_buffer _buffer; 				      \
+    __libc_maybe_call (_pthread_cleanup_push, (&_buffer, (fct), (arg)), 0)
+
+#define __libc_cleanup_pop(execute) \
+    __libc_maybe_call (_pthread_cleanup_pop, (&_buffer, execute), 0);	      \
+    }
+#endif
+
+/* Create thread-specific key.  */
+#define __libc_key_create(KEY, DESTRUCTOR) \
+  (__libc_maybe_call (__pthread_key_create, (KEY, DESTRUCTOR), 1))
+
+/* Get thread-specific data.  */
+#define __libc_getspecific(KEY) \
+  (__libc_maybe_call (__pthread_getspecific, (KEY), NULL))
+
+/* Set thread-specific data.  */
+#define __libc_setspecific(KEY, VALUE) \
+  (__libc_maybe_call (__pthread_setspecific, (KEY, VALUE), 0))
+
+
+/* Register handlers to execute before and after `fork'.  */
+#define __libc_atfork(PREPARE, PARENT, CHILD) \
+  (__libc_maybe_call (__pthread_atfork, (PREPARE, PARENT, CHILD), 0))
+
+/* Functions that are used by this file and are internal to the GNU C
+   library.  */
+
+extern int __pthread_mutex_init (pthread_mutex_t *__mutex,
+				 const pthread_mutexattr_t *__mutex_attr);
+
+extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex);
+
+extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex);
+
+extern int __pthread_mutex_lock (pthread_mutex_t *__mutex);
+
+extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex);
+
+extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr);
+
+extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr);
+
+extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr,
+					int __kind);
+
+#ifdef __USE_UNIX98
+extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock,
+				  const pthread_rwlockattr_t *__attr);
+
+extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock);
+
+extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock);
+
+extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock);
+
+extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock);
+
+extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock);
+
+extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock);
+#endif
+
+extern int __pthread_key_create (pthread_key_t *__key,
+				 void (*__destr_function) (void *));
+
+extern int __pthread_setspecific (pthread_key_t __key,
+				  const void *__pointer);
+
+extern void *__pthread_getspecific (pthread_key_t __key);
+
+extern int __pthread_once (pthread_once_t *__once_control,
+			   void (*__init_routine) (void));
+
+extern int __pthread_atfork (void (*__prepare) (void),
+			     void (*__parent) (void),
+			     void (*__child) (void));
+
+
+
+/* Make the pthread functions weak so that we can elide them from
+   single-threaded processes.  */
+#ifndef __NO_WEAK_PTHREAD_ALIASES
+# ifdef weak_extern
+#   define BP_SYM(sym) sym
+weak_extern (BP_SYM (__pthread_mutex_init))
+weak_extern (BP_SYM (__pthread_mutex_destroy))
+weak_extern (BP_SYM (__pthread_mutex_lock))
+weak_extern (BP_SYM (__pthread_mutex_trylock))
+weak_extern (BP_SYM (__pthread_mutex_unlock))
+weak_extern (BP_SYM (__pthread_mutexattr_init))
+weak_extern (BP_SYM (__pthread_mutexattr_destroy))
+weak_extern (BP_SYM (__pthread_mutexattr_settype))
+weak_extern (BP_SYM (__pthread_rwlock_init))
+weak_extern (BP_SYM (__pthread_rwlock_destroy))
+weak_extern (BP_SYM (__pthread_rwlock_rdlock))
+weak_extern (BP_SYM (__pthread_rwlock_tryrdlock))
+weak_extern (BP_SYM (__pthread_rwlock_wrlock))
+weak_extern (BP_SYM (__pthread_rwlock_trywrlock))
+weak_extern (BP_SYM (__pthread_rwlock_unlock))
+weak_extern (BP_SYM (__pthread_key_create))
+weak_extern (BP_SYM (__pthread_setspecific))
+weak_extern (BP_SYM (__pthread_getspecific))
+weak_extern (BP_SYM (__pthread_once))
+weak_extern (__pthread_atfork)
+weak_extern (BP_SYM (_pthread_cleanup_push))
+weak_extern (BP_SYM (_pthread_cleanup_pop))
+weak_extern (BP_SYM (_pthread_cleanup_push_defer))
+weak_extern (BP_SYM (_pthread_cleanup_pop_restore))
+# else
+#  pragma weak __pthread_mutex_init
+#  pragma weak __pthread_mutex_destroy
+#  pragma weak __pthread_mutex_lock
+#  pragma weak __pthread_mutex_trylock
+#  pragma weak __pthread_mutex_unlock
+#  pragma weak __pthread_mutexattr_init
+#  pragma weak __pthread_mutexattr_destroy
+#  pragma weak __pthread_mutexattr_settype
+#  pragma weak __pthread_rwlock_destroy
+#  pragma weak __pthread_rwlock_rdlock
+#  pragma weak __pthread_rwlock_tryrdlock
+#  pragma weak __pthread_rwlock_wrlock
+#  pragma weak __pthread_rwlock_trywrlock
+#  pragma weak __pthread_rwlock_unlock
+#  pragma weak __pthread_key_create
+#  pragma weak __pthread_setspecific
+#  pragma weak __pthread_getspecific
+#  pragma weak __pthread_once
+#  pragma weak __pthread_atfork
+#  pragma weak _pthread_cleanup_push_defer
+#  pragma weak _pthread_cleanup_pop_restore
+#  pragma weak _pthread_cleanup_push
+#  pragma weak _pthread_cleanup_pop
+# endif
+#endif
+
+/* We need portable names for some functions.  E.g., when they are
+   used as argument to __libc_cleanup_region_start.  */
+#define __libc_mutex_unlock __pthread_mutex_unlock
+
+#endif	/* bits/libc-lock.h */

+ 69 - 0
libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-tsd.h

@@ -0,0 +1,69 @@
+/* libc-internal interface for thread-specific data.  LinuxThreads version.
+   Copyright (C) 1997-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; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _BITS_LIBC_TSD_H
+#define _BITS_LIBC_TSD_H 1
+
+/* Fast thread-specific data internal to libc.  */
+enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0,
+			_LIBC_TSD_KEY_DL_ERROR,
+			_LIBC_TSD_KEY_RPC_VARS,
+			_LIBC_TSD_KEY_LOCALE,
+			_LIBC_TSD_KEY_CTYPE_B,
+			_LIBC_TSD_KEY_CTYPE_TOLOWER,
+			_LIBC_TSD_KEY_CTYPE_TOUPPER,
+			_LIBC_TSD_KEY_N };
+
+#include <features.h>
+#include <linuxthreads.old/internals.h>
+
+#ifdef __UCLIBC_HAS_TLS__
+#include <tls.h>
+
+/* When __thread works, the generic definition is what we want.  */
+# include <sysdeps/generic/bits/libc-tsd.h>
+
+#else
+
+# include <bits/libc-lock.h>
+
+# ifndef SHARED
+extern void ** __pthread_internal_tsd_address (int);
+extern void *__pthread_internal_tsd_get (int);
+extern int __pthread_internal_tsd_set (int, const void *);
+
+weak_extern (__pthread_internal_tsd_address)
+weak_extern (__pthread_internal_tsd_get)
+weak_extern (__pthread_internal_tsd_set)
+# endif
+
+#define __libc_tsd_define(CLASS, KEY)	CLASS void *__libc_tsd_##KEY##_data;
+#define __libc_tsd_address(KEY) \
+  __libc_maybe_call2 (pthread_internal_tsd_address,			\
+		      (_LIBC_TSD_KEY_##KEY), &__libc_tsd_##KEY##_data)
+#define __libc_tsd_get(KEY) \
+  __libc_maybe_call2 (pthread_internal_tsd_get,				\
+		      (_LIBC_TSD_KEY_##KEY), __libc_tsd_##KEY##_data)
+#define __libc_tsd_set(KEY, VALUE) \
+  __libc_maybe_call2 (pthread_internal_tsd_set,				\
+		      (_LIBC_TSD_KEY_##KEY, (VALUE)),			\
+		       (__libc_tsd_##KEY##_data = (VALUE), 0))
+
+#endif
+
+#endif	/* bits/libc-tsd.h */

+ 145 - 0
libpthread/linuxthreads.old/sysdeps/pthread/bits/pthreadtypes.h

@@ -0,0 +1,145 @@
+/* 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_size_t
+#include <stddef.h>
+
+#define __need_schedparam
+#include <bits/sched.h>
+
+/* 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,
+			  adaptive SMP lock stores spin count here. */
+};
+
+#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;
+
+
+#if defined __USE_UNIX98 || defined __USE_XOPEN2K
+/* 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;
+
+/* 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 */

+ 113 - 0
libpthread/linuxthreads.old/sysdeps/pthread/not-cancel.h

@@ -0,0 +1,113 @@
+/* Uncancelable versions of cancelable interfaces.  Linux version.
+   Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/types.h>
+#include <sysdep.h>
+
+/* Uncancelable open.  */
+#if defined __NR_openat && !defined __NR_open
+#define open_not_cancel(name, flags, mode) \
+	INLINE_SYSCALL (openat, 4, AT_FDCWD, (const char *) (name), \
+		(flags), (mode))
+#define open_not_cancel_2(name, flags) \
+	INLINE_SYSCALL (openat, 3, AT_FDCWD, (const char *) (name), \
+		(flags))
+#else
+#define open_not_cancel(name, flags, mode) \
+   INLINE_SYSCALL (open, 3, (const char *) (name), (flags), (mode))
+#define open_not_cancel_2(name, flags) \
+   INLINE_SYSCALL (open, 2, (const char *) (name), (flags))
+#endif
+
+/* Uncancelable openat.  */
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+extern int __openat_nocancel (int fd, const char *fname, int oflag,
+			      mode_t mode) attribute_hidden;
+extern int __openat64_nocancel (int fd, const char *fname, int oflag,
+				mode_t mode) attribute_hidden;
+#else
+# define __openat_nocancel(fd, fname, oflag, mode) \
+  openat (fd, fname, oflag, mode)
+# define __openat64_nocancel(fd, fname, oflag, mode) \
+  openat64 (fd, fname, oflag, mode)
+#endif
+
+#define openat_not_cancel(fd, fname, oflag, mode) \
+  __openat_nocancel (fd, fname, oflag, mode)
+#define openat_not_cancel_3(fd, fname, oflag) \
+  __openat_nocancel (fd, fname, oflag, 0)
+#define openat64_not_cancel(fd, fname, oflag, mode) \
+  __openat64_nocancel (fd, fname, oflag, mode)
+#define openat64_not_cancel_3(fd, fname, oflag) \
+  __openat64_nocancel (fd, fname, oflag, 0)
+
+/* Uncancelable close.  */
+#define close_not_cancel(fd) \
+  INLINE_SYSCALL (close, 1, fd)
+#define close_not_cancel_no_status(fd) \
+  (void) ({ INTERNAL_SYSCALL_DECL (err);				      \
+	    INTERNAL_SYSCALL (close, err, 1, (fd)); })
+
+/* Uncancelable read.  */
+#define read_not_cancel(fd, buf, n) \
+  INLINE_SYSCALL (read, 3, (fd), (buf), (n))
+
+/* Uncancelable write.  */
+#define write_not_cancel(fd, buf, n) \
+  INLINE_SYSCALL (write, 3, (fd), (buf), (n))
+
+/* Uncancelable writev.  */
+#define writev_not_cancel_no_status(fd, iov, n) \
+  (void) ({ INTERNAL_SYSCALL_DECL (err);				      \
+	    INTERNAL_SYSCALL (writev, err, 3, (fd), (iov), (n)); })
+
+/* Uncancelable fcntl.  */
+#define fcntl_not_cancel(fd, cmd, val) \
+  __fcntl_nocancel (fd, cmd, val)
+
+/* Uncancelable waitpid.  */
+#ifdef __NR_waitpid
+# define waitpid_not_cancel(pid, stat_loc, options) \
+  INLINE_SYSCALL (waitpid, 3, pid, stat_loc, options)
+#else
+# define waitpid_not_cancel(pid, stat_loc, options) \
+  INLINE_SYSCALL (wait4, 4, pid, stat_loc, options, NULL)
+#endif
+
+/* Uncancelable pause.  */
+#ifdef __NR_pause
+# define pause_not_cancel() \
+  INLINE_SYSCALL (pause, 0)
+#else
+# define pause_not_cancel() \
+  __pause_nocancel ()
+#endif
+
+/* Uncancelable nanosleep.  */
+#ifdef __NR_nanosleep
+# define nanosleep_not_cancel(requested_time, remaining) \
+  INLINE_SYSCALL (nanosleep, 2, requested_time, remaining)
+#else
+# define nanosleep_not_cancel(requested_time, remaining) \
+  __nanosleep_nocancel (requested_time, remaining)
+#endif
+
+/* Uncancelable sigsuspend.  */
+#define sigsuspend_not_cancel(set) \
+  __sigsuspend_nocancel (set)

+ 113 - 0
libpthread/linuxthreads.old/sysdeps/pthread/pthread-functions.h

@@ -0,0 +1,113 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _PTHREAD_FUNCTIONS_H
+#define _PTHREAD_FUNCTIONS_H	1
+
+#include <pthread.h>
+#if 0
+#include <setjmp.h>
+#include <linuxthreads.old/internals.h>
+
+struct fork_block;
+#endif
+
+/* Data type shared with libc.  The libc uses it to pass on calls to
+   the thread functions.  Wine pokes directly into this structure,
+   so if possible avoid breaking it and append new hooks to the end.  */
+struct pthread_functions
+{
+#if 0
+  pid_t (*ptr_pthread_fork) (struct fork_block *);
+#endif
+  int (*ptr_pthread_attr_destroy) (pthread_attr_t *);
+  int (*ptr_pthread_attr_init) (pthread_attr_t *);
+  int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *);
+  int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int);
+  int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *);
+  int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int);
+  int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *,
+					 struct sched_param *);
+  int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *,
+					 const struct sched_param *);
+  int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *);
+  int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int);
+  int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *);
+  int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int);
+  int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *);
+  int (*ptr_pthread_condattr_init) (pthread_condattr_t *);
+  int (*ptr_pthread_cond_broadcast) (pthread_cond_t *);
+  int (*ptr_pthread_cond_destroy) (pthread_cond_t *);
+  int (*ptr_pthread_cond_init) (pthread_cond_t *,
+				  const pthread_condattr_t *);
+  int (*ptr_pthread_cond_signal) (pthread_cond_t *);
+  int (*ptr_pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *);
+  int (*ptr_pthread_equal) (pthread_t, pthread_t);
+  void (*ptr___pthread_exit) (void *);
+  int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *);
+  int (*ptr_pthread_setschedparam) (pthread_t, int,
+				    const struct sched_param *);
+  int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *);
+  int (*ptr_pthread_mutex_init) (pthread_mutex_t *,
+				 const pthread_mutexattr_t *);
+  int (*ptr_pthread_mutex_lock) (pthread_mutex_t *);
+  int (*ptr_pthread_mutex_trylock) (pthread_mutex_t *);
+  int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *);
+  pthread_t (*ptr_pthread_self) (void);
+  int (*ptr_pthread_setcancelstate) (int, int *);
+  int (*ptr_pthread_setcanceltype) (int, int *);
+#if 0
+  void (*ptr_pthread_do_exit) (void *retval, char *currentframe);
+  void (*ptr_pthread_cleanup_upto) (__jmp_buf target,
+				    char *targetframe);
+  pthread_descr (*ptr_pthread_thread_self) (void);
+#endif
+#if !defined __UCLIBC_HAS_TLS__ && defined __UCLIBC_HAS_RPC__
+  int (*ptr_pthread_internal_tsd_set) (int key, const void *pointer);
+  void * (*ptr_pthread_internal_tsd_get) (int key);
+  void ** __attribute__ ((__const__))
+    (*ptr_pthread_internal_tsd_address) (int key);
+#endif
+#if 0
+  int (*ptr_pthread_sigaction) (int sig, const struct sigaction * act,
+				struct sigaction *oact);
+  int (*ptr_pthread_sigwait) (const sigset_t *set, int *sig);
+  int (*ptr_pthread_raise) (int sig);
+#endif
+  int (*ptr_pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *,
+				       const struct timespec *);
+#if 0
+  void (*ptr__pthread_cleanup_push) (struct _pthread_cleanup_buffer * buffer,
+				     void (*routine)(void *), void * arg);
+#endif
+  void (*ptr__pthread_cleanup_push_defer) (struct _pthread_cleanup_buffer * buffer,
+					   void (*routine)(void *), void * arg);
+#if 0
+  void (*ptr__pthread_cleanup_pop) (struct _pthread_cleanup_buffer * buffer,
+				    int execute);
+#endif
+  void (*ptr__pthread_cleanup_pop_restore) (struct _pthread_cleanup_buffer * buffer,
+					    int execute);
+};
+
+/* Variable in libc.so.  */
+extern struct pthread_functions __libc_pthread_functions attribute_hidden;
+
+extern int * __libc_pthread_init (const struct pthread_functions *functions);
+
+#endif	/* pthread-functions.h */

+ 710 - 0
libpthread/linuxthreads.old/sysdeps/pthread/pthread.h

@@ -0,0 +1,710 @@
+/* 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.                 */
+
+#ifndef _PTHREAD_H
+#define _PTHREAD_H	1
+
+#include <features.h>
+
+#include <sched.h>
+#include <time.h>
+
+#define __need_sigset_t
+#include <signal.h>
+#include <bits/pthreadtypes.h>
+#include <bits/initspin.h>
+
+
+__BEGIN_DECLS
+
+/* Initializers.  */
+
+#define PTHREAD_MUTEX_INITIALIZER \
+  {0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, __LOCK_INITIALIZER}
+#ifdef __USE_GNU
+# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \
+  {0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, __LOCK_INITIALIZER}
+# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \
+  {0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, __LOCK_INITIALIZER}
+# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \
+  {0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, __LOCK_INITIALIZER}
+#endif
+
+#define PTHREAD_COND_INITIALIZER {__LOCK_INITIALIZER, 0}
+
+#if defined __USE_UNIX98 || defined __USE_XOPEN2K
+# define PTHREAD_RWLOCK_INITIALIZER \
+  { __LOCK_INITIALIZER, 0, NULL, NULL, NULL,				      \
+    PTHREAD_RWLOCK_DEFAULT_NP, PTHREAD_PROCESS_PRIVATE }
+#endif
+#ifdef __USE_GNU
+# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \
+  { __LOCK_INITIALIZER, 0, NULL, NULL, NULL,				      \
+    PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, PTHREAD_PROCESS_PRIVATE }
+#endif
+
+/* Values for attributes.  */
+
+enum
+{
+  PTHREAD_CREATE_JOINABLE,
+#define PTHREAD_CREATE_JOINABLE	PTHREAD_CREATE_JOINABLE
+  PTHREAD_CREATE_DETACHED
+#define PTHREAD_CREATE_DETACHED	PTHREAD_CREATE_DETACHED
+};
+
+enum
+{
+  PTHREAD_INHERIT_SCHED,
+#define PTHREAD_INHERIT_SCHED	PTHREAD_INHERIT_SCHED
+  PTHREAD_EXPLICIT_SCHED
+#define PTHREAD_EXPLICIT_SCHED	PTHREAD_EXPLICIT_SCHED
+};
+
+enum
+{
+  PTHREAD_SCOPE_SYSTEM,
+#define PTHREAD_SCOPE_SYSTEM	PTHREAD_SCOPE_SYSTEM
+  PTHREAD_SCOPE_PROCESS
+#define PTHREAD_SCOPE_PROCESS	PTHREAD_SCOPE_PROCESS
+};
+
+enum
+{
+  PTHREAD_MUTEX_ADAPTIVE_NP,
+  PTHREAD_MUTEX_RECURSIVE_NP,
+  PTHREAD_MUTEX_ERRORCHECK_NP,
+  PTHREAD_MUTEX_TIMED_NP
+#ifdef __USE_UNIX98
+  ,
+  PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_ADAPTIVE_NP,
+  PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
+  PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
+  PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
+#endif
+#ifdef __USE_GNU
+  /* For compatibility.  */
+  , PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_ADAPTIVE_NP
+#endif
+};
+
+enum
+{
+  PTHREAD_PROCESS_PRIVATE,
+#define PTHREAD_PROCESS_PRIVATE	PTHREAD_PROCESS_PRIVATE
+  PTHREAD_PROCESS_SHARED
+#define PTHREAD_PROCESS_SHARED	PTHREAD_PROCESS_SHARED
+};
+
+#if defined __USE_UNIX98 || defined __USE_XOPEN2K
+enum
+{
+  PTHREAD_RWLOCK_PREFER_READER_NP,
+  PTHREAD_RWLOCK_PREFER_WRITER_NP,
+  PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,
+  PTHREAD_RWLOCK_DEFAULT_NP = PTHREAD_RWLOCK_PREFER_WRITER_NP
+};
+#endif	/* Unix98 */
+
+#define PTHREAD_ONCE_INIT 0
+
+/* Special constants */
+
+#ifdef __USE_XOPEN2K
+/* -1 is distinct from 0 and all errno constants */
+# define PTHREAD_BARRIER_SERIAL_THREAD -1
+#endif
+
+/* Cleanup buffers */
+
+struct _pthread_cleanup_buffer
+{
+  void (*__routine) (void *);		  /* Function to call.  */
+  void *__arg;				  /* Its argument.  */
+  int __canceltype;			  /* Saved cancellation type. */
+  struct _pthread_cleanup_buffer *__prev; /* Chaining of cleanup functions.  */
+};
+
+/* Cancellation */
+
+enum
+{
+  PTHREAD_CANCEL_ENABLE,
+#define PTHREAD_CANCEL_ENABLE	PTHREAD_CANCEL_ENABLE
+  PTHREAD_CANCEL_DISABLE
+#define PTHREAD_CANCEL_DISABLE	PTHREAD_CANCEL_DISABLE
+};
+enum
+{
+  PTHREAD_CANCEL_DEFERRED,
+#define PTHREAD_CANCEL_DEFERRED	PTHREAD_CANCEL_DEFERRED
+  PTHREAD_CANCEL_ASYNCHRONOUS
+#define PTHREAD_CANCEL_ASYNCHRONOUS	PTHREAD_CANCEL_ASYNCHRONOUS
+};
+#define PTHREAD_CANCELED ((void *) -1)
+
+
+/* Function for handling threads.  */
+
+/* Create a thread with given attributes ATTR (or default attributes
+   if ATTR is NULL), and call function START_ROUTINE with given
+   arguments ARG.  */
+extern int pthread_create (pthread_t *__restrict __threadp,
+			   const pthread_attr_t *__restrict __attr,
+			   void *(*__start_routine) (void *),
+			   void *__restrict __arg) __THROW;
+
+/* Obtain the identifier of the current thread.  */
+extern pthread_t pthread_self (void) __THROW;
+
+/* Compare two thread identifiers.  */
+extern int pthread_equal (pthread_t __thread1, pthread_t __thread2) __THROW;
+
+/* Terminate calling thread.  */
+extern void pthread_exit (void *__retval) __attribute__ ((__noreturn__));
+
+/* Make calling thread wait for termination of the thread TH.  The
+   exit status of the thread is stored in *THREAD_RETURN, if THREAD_RETURN
+   is not NULL.  */
+extern int pthread_join (pthread_t __th, void **__thread_return);
+
+/* Indicate that the thread TH is never to be joined with PTHREAD_JOIN.
+   The resources of TH will therefore be freed immediately when it
+   terminates, instead of waiting for another thread to perform PTHREAD_JOIN
+   on it.  */
+extern int pthread_detach (pthread_t __th) __THROW;
+
+
+/* Functions for handling attributes.  */
+
+/* Initialize thread attribute *ATTR with default attributes
+   (detachstate is PTHREAD_JOINABLE, scheduling policy is SCHED_OTHER,
+    no user-provided stack).  */
+extern int pthread_attr_init (pthread_attr_t *__attr) __THROW;
+
+/* Destroy thread attribute *ATTR.  */
+extern int pthread_attr_destroy (pthread_attr_t *__attr) __THROW;
+
+/* Set the `detachstate' attribute in *ATTR according to DETACHSTATE.  */
+extern int pthread_attr_setdetachstate (pthread_attr_t *__attr,
+					int __detachstate) __THROW;
+
+/* Return in *DETACHSTATE the `detachstate' attribute in *ATTR.  */
+extern int pthread_attr_getdetachstate (const pthread_attr_t *__attr,
+					int *__detachstate) __THROW;
+
+/* Set scheduling parameters (priority, etc) in *ATTR according to PARAM.  */
+extern int pthread_attr_setschedparam (pthread_attr_t *__restrict __attr,
+				       const struct sched_param *__restrict
+				       __param) __THROW;
+
+/* Return in *PARAM the scheduling parameters of *ATTR.  */
+extern int pthread_attr_getschedparam (const pthread_attr_t *__restrict
+				       __attr,
+				       struct sched_param *__restrict __param)
+     __THROW;
+
+/* Set scheduling policy in *ATTR according to POLICY.  */
+extern int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy)
+     __THROW;
+
+/* Return in *POLICY the scheduling policy of *ATTR.  */
+extern int pthread_attr_getschedpolicy (const pthread_attr_t *__restrict
+					__attr, int *__restrict __policy)
+     __THROW;
+
+/* Set scheduling inheritance mode in *ATTR according to INHERIT.  */
+extern int pthread_attr_setinheritsched (pthread_attr_t *__attr,
+					 int __inherit) __THROW;
+
+/* Return in *INHERIT the scheduling inheritance mode of *ATTR.  */
+extern int pthread_attr_getinheritsched (const pthread_attr_t *__restrict
+					 __attr, int *__restrict __inherit)
+     __THROW;
+
+/* Set scheduling contention scope in *ATTR according to SCOPE.  */
+extern int pthread_attr_setscope (pthread_attr_t *__attr, int __scope)
+     __THROW;
+
+/* Return in *SCOPE the scheduling contention scope of *ATTR.  */
+extern int pthread_attr_getscope (const pthread_attr_t *__restrict __attr,
+				  int *__restrict __scope) __THROW;
+
+#ifdef __USE_UNIX98
+/* Set the size of the guard area at the bottom of the thread.  */
+extern int pthread_attr_setguardsize (pthread_attr_t *__attr,
+				      size_t __guardsize) __THROW;
+
+/* Get the size of the guard area at the bottom of the thread.  */
+extern int pthread_attr_getguardsize (const pthread_attr_t *__restrict
+				      __attr, size_t *__restrict __guardsize)
+     __THROW;
+#endif
+
+#if 0 /* uClibc: deprecated stuff disabled. def __UCLIBC_SUSV3_LEGACY__ */
+/* Set the starting address of the stack of the thread to be created.
+   Depending on whether the stack grows up or down the value must either
+   be higher or lower than all the address in the memory block.  The
+   minimal size of the block must be PTHREAD_STACK_SIZE.  */
+extern int pthread_attr_setstackaddr (pthread_attr_t *__attr,
+				      void *__stackaddr) __THROW;
+
+/* Return the previously set address for the stack.  */
+extern int pthread_attr_getstackaddr (const pthread_attr_t *__restrict
+				      __attr, void **__restrict __stackaddr)
+     __THROW;
+#endif
+
+#ifdef __USE_XOPEN2K
+/* The following two interfaces are intended to replace the last two.  They
+   require setting the address as well as the size since only setting the
+   address will make the implementation on some architectures impossible.  */
+extern int pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr,
+				  size_t __stacksize) __THROW;
+
+/* Return the previously set address for the stack.  */
+extern int pthread_attr_getstack (const pthread_attr_t *__restrict __attr,
+				  void **__restrict __stackaddr,
+				  size_t *__restrict __stacksize) __THROW;
+#endif
+
+/* Add information about the minimum stack size needed for the thread
+   to be started.  This size must never be less than PTHREAD_STACK_SIZE
+   and must also not exceed the system limits.  */
+extern int pthread_attr_setstacksize (pthread_attr_t *__attr,
+				      size_t __stacksize) __THROW;
+
+/* Return the currently used minimal stack size.  */
+extern int pthread_attr_getstacksize (const pthread_attr_t *__restrict
+				      __attr, size_t *__restrict __stacksize)
+     __THROW;
+
+#if 0
+/* Not yet implemented in uClibc! */
+
+#ifdef __USE_GNU
+/* Initialize thread attribute *ATTR with attributes corresponding to the
+   already running thread TH.  It shall be called on uninitialized ATTR
+   and destroyed with pthread_attr_destroy when no longer needed.  */
+extern int pthread_getattr_np (pthread_t __th, pthread_attr_t *__attr) __THROW;
+#endif
+#endif
+
+/* Functions for scheduling control.  */
+
+/* Set the scheduling parameters for TARGET_THREAD according to POLICY
+   and *PARAM.  */
+extern int pthread_setschedparam (pthread_t __target_thread, int __policy,
+				  const struct sched_param *__param)
+     __THROW;
+
+/* Return in *POLICY and *PARAM the scheduling parameters for TARGET_THREAD.  */
+extern int pthread_getschedparam (pthread_t __target_thread,
+				  int *__restrict __policy,
+				  struct sched_param *__restrict __param)
+     __THROW;
+
+#ifdef __USE_UNIX98
+/* Determine level of concurrency.  */
+extern int pthread_getconcurrency (void) __THROW;
+
+/* Set new concurrency level to LEVEL.  */
+extern int pthread_setconcurrency (int __level) __THROW;
+#endif
+
+#ifdef __USE_GNU
+/* Same thing, different name */
+#define pthread_yield() sched_yield()
+#endif
+
+/* Functions for mutex handling.  */
+
+/* Initialize MUTEX using attributes in *MUTEX_ATTR, or use the
+   default values if later is NULL.  */
+extern int pthread_mutex_init (pthread_mutex_t *__restrict __mutex,
+			       const pthread_mutexattr_t *__restrict
+			       __mutex_attr) __THROW;
+
+/* Destroy MUTEX.  */
+extern int pthread_mutex_destroy (pthread_mutex_t *__mutex) __THROW;
+
+/* Try to lock MUTEX.  */
+extern int pthread_mutex_trylock (pthread_mutex_t *__mutex) __THROW;
+
+/* Wait until lock for MUTEX becomes available and lock it.  */
+extern int pthread_mutex_lock (pthread_mutex_t *__mutex) __THROW;
+
+#ifdef __USE_XOPEN2K
+/* Wait until lock becomes available, or specified time passes. */
+extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex,
+				    const struct timespec *__restrict
+				    __abstime) __THROW;
+#endif
+
+/* Unlock MUTEX.  */
+extern int pthread_mutex_unlock (pthread_mutex_t *__mutex) __THROW;
+
+
+/* Functions for handling mutex attributes.  */
+
+/* Initialize mutex attribute object ATTR with default attributes
+   (kind is PTHREAD_MUTEX_TIMED_NP).  */
+extern int pthread_mutexattr_init (pthread_mutexattr_t *__attr) __THROW;
+
+/* Destroy mutex attribute object ATTR.  */
+extern int pthread_mutexattr_destroy (pthread_mutexattr_t *__attr) __THROW;
+
+/* Get the process-shared flag of the mutex attribute ATTR.  */
+extern int pthread_mutexattr_getpshared (const pthread_mutexattr_t *
+					 __restrict __attr,
+					 int *__restrict __pshared) __THROW;
+
+/* Set the process-shared flag of the mutex attribute ATTR.  */
+extern int pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr,
+					 int __pshared) __THROW;
+
+#ifdef __USE_UNIX98
+/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL,
+   PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or
+   PTHREAD_MUTEX_DEFAULT).  */
+extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind)
+     __THROW;
+
+/* Return in *KIND the mutex kind attribute in *ATTR.  */
+extern int pthread_mutexattr_gettype (const pthread_mutexattr_t *__restrict
+				      __attr, int *__restrict __kind) __THROW;
+#endif
+
+
+/* Functions for handling conditional variables.  */
+
+/* Initialize condition variable COND using attributes ATTR, or use
+   the default values if later is NULL.  */
+extern int pthread_cond_init (pthread_cond_t *__restrict __cond,
+			      const pthread_condattr_t *__restrict
+			      __cond_attr) __THROW;
+libpthread_hidden_proto(pthread_cond_init)
+
+/* Destroy condition variable COND.  */
+extern int pthread_cond_destroy (pthread_cond_t *__cond) __THROW;
+libpthread_hidden_proto(pthread_cond_destroy)
+
+/* Wake up one thread waiting for condition variable COND.  */
+extern int pthread_cond_signal (pthread_cond_t *__cond) __THROW;
+libpthread_hidden_proto(pthread_cond_signal)
+
+/* Wake up all threads waiting for condition variables COND.  */
+extern int pthread_cond_broadcast (pthread_cond_t *__cond) __THROW;
+libpthread_hidden_proto(pthread_cond_broadcast)
+
+/* Wait for condition variable COND to be signaled or broadcast.
+   MUTEX is assumed to be locked before.  */
+extern int pthread_cond_wait (pthread_cond_t *__restrict __cond,
+			      pthread_mutex_t *__restrict __mutex);
+libpthread_hidden_proto(pthread_cond_wait)
+
+/* Wait for condition variable COND to be signaled or broadcast until
+   ABSTIME.  MUTEX is assumed to be locked before.  ABSTIME is an
+   absolute time specification; zero is the beginning of the epoch
+   (00:00:00 GMT, January 1, 1970).  */
+extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond,
+				   pthread_mutex_t *__restrict __mutex,
+				   const struct timespec *__restrict
+				   __abstime);
+libpthread_hidden_proto(pthread_cond_timedwait)
+
+/* Functions for handling condition variable attributes.  */
+
+/* Initialize condition variable attribute ATTR.  */
+extern int pthread_condattr_init (pthread_condattr_t *__attr) __THROW;
+libpthread_hidden_proto(pthread_condattr_init)
+
+/* Destroy condition variable attribute ATTR.  */
+extern int pthread_condattr_destroy (pthread_condattr_t *__attr) __THROW;
+libpthread_hidden_proto(pthread_condattr_destroy)
+
+/* Get the process-shared flag of the condition variable attribute ATTR.  */
+extern int pthread_condattr_getpshared (const pthread_condattr_t *
+					__restrict __attr,
+					int *__restrict __pshared) __THROW;
+
+/* Set the process-shared flag of the condition variable attribute ATTR.  */
+extern int pthread_condattr_setpshared (pthread_condattr_t *__attr,
+					int __pshared) __THROW;
+
+
+#if defined __USE_UNIX98 || defined __USE_XOPEN2K
+/* Functions for handling read-write locks.  */
+
+/* Initialize read-write lock RWLOCK using attributes ATTR, or use
+   the default values if later is NULL.  */
+extern int pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock,
+				const pthread_rwlockattr_t *__restrict
+				__attr) __THROW;
+
+/* Destroy read-write lock RWLOCK.  */
+extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock) __THROW;
+
+/* Acquire read lock for RWLOCK.  */
+extern int pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock) __THROW;
+
+/* Try to acquire read lock for RWLOCK.  */
+extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock) __THROW;
+
+# ifdef __USE_XOPEN2K
+/* Try to acquire read lock for RWLOCK or return after specfied time.  */
+extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock,
+				       const struct timespec *__restrict
+				       __abstime) __THROW;
+# endif
+
+/* Acquire write lock for RWLOCK.  */
+extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock) __THROW;
+
+/* Try to acquire write lock for RWLOCK.  */
+extern int pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock) __THROW;
+
+# ifdef __USE_XOPEN2K
+/* Try to acquire write lock for RWLOCK or return after specfied time.  */
+extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock,
+				       const struct timespec *__restrict
+				       __abstime) __THROW;
+# endif
+
+/* Unlock RWLOCK.  */
+extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock) __THROW;
+
+
+/* Functions for handling read-write lock attributes.  */
+
+/* Initialize attribute object ATTR with default values.  */
+extern int pthread_rwlockattr_init (pthread_rwlockattr_t *__attr) __THROW;
+
+/* Destroy attribute object ATTR.  */
+extern int pthread_rwlockattr_destroy (pthread_rwlockattr_t *__attr) __THROW;
+
+/* Return current setting of process-shared attribute of ATTR in PSHARED.  */
+extern int pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *
+					  __restrict __attr,
+					  int *__restrict __pshared) __THROW;
+
+/* Set process-shared attribute of ATTR to PSHARED.  */
+extern int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *__attr,
+					  int __pshared) __THROW;
+
+/* Return current setting of reader/writer preference.  */
+extern int pthread_rwlockattr_getkind_np (const pthread_rwlockattr_t *__attr,
+					  int *__pref) __THROW;
+
+/* Set reader/write preference.  */
+extern int pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *__attr,
+					  int __pref) __THROW;
+#endif
+
+#if 0
+/* Not yet implemented in uClibc! */
+
+#ifdef __USE_XOPEN2K
+/* The IEEE Std. 1003.1j-2000 introduces functions to implement
+   spinlocks.  */
+
+/* Initialize the spinlock LOCK.  If PSHARED is nonzero the spinlock can
+   be shared between different processes.  */
+extern int pthread_spin_init (pthread_spinlock_t *__lock, int __pshared)
+     __THROW;
+
+/* Destroy the spinlock LOCK.  */
+extern int pthread_spin_destroy (pthread_spinlock_t *__lock) __THROW;
+
+/* Wait until spinlock LOCK is retrieved.  */
+extern int pthread_spin_lock (pthread_spinlock_t *__lock) __THROW;
+
+/* Try to lock spinlock LOCK.  */
+extern int pthread_spin_trylock (pthread_spinlock_t *__lock) __THROW;
+
+/* Release spinlock LOCK.  */
+extern int pthread_spin_unlock (pthread_spinlock_t *__lock) __THROW;
+
+
+/* Barriers are a also a new feature in 1003.1j-2000. */
+
+extern int pthread_barrier_init (pthread_barrier_t *__restrict __barrier,
+				 const pthread_barrierattr_t *__restrict
+				 __attr, unsigned int __count) __THROW;
+
+extern int pthread_barrier_destroy (pthread_barrier_t *__barrier) __THROW;
+
+extern int pthread_barrierattr_init (pthread_barrierattr_t *__attr) __THROW;
+
+extern int pthread_barrierattr_destroy (pthread_barrierattr_t *__attr) __THROW;
+
+extern int pthread_barrierattr_getpshared (const pthread_barrierattr_t *
+					   __restrict __attr,
+					   int *__restrict __pshared) __THROW;
+
+extern int pthread_barrierattr_setpshared (pthread_barrierattr_t *__attr,
+					   int __pshared) __THROW;
+
+extern int pthread_barrier_wait (pthread_barrier_t *__barrier) __THROW;
+#endif
+#endif
+
+
+/* Functions for handling thread-specific data.  */
+
+/* Create a key value identifying a location in the thread-specific
+   data area.  Each thread maintains a distinct thread-specific data
+   area.  DESTR_FUNCTION, if non-NULL, is called with the value
+   associated to that key when the key is destroyed.
+   DESTR_FUNCTION is not called if the value associated is NULL when
+   the key is destroyed.  */
+extern int pthread_key_create (pthread_key_t *__key,
+			       void (*__destr_function) (void *)) __THROW;
+
+/* Destroy KEY.  */
+extern int pthread_key_delete (pthread_key_t __key) __THROW;
+
+/* Store POINTER in the thread-specific data slot identified by KEY. */
+extern int pthread_setspecific (pthread_key_t __key,
+				const void *__pointer) __THROW;
+
+/* Return current value of the thread-specific data slot identified by KEY.  */
+extern void *pthread_getspecific (pthread_key_t __key) __THROW;
+
+
+/* Functions for handling initialization.  */
+
+/* Guarantee that the initialization function INIT_ROUTINE will be called
+   only once, even if pthread_once is executed several times with the
+   same ONCE_CONTROL argument. ONCE_CONTROL must point to a static or
+   extern variable initialized to PTHREAD_ONCE_INIT.
+
+   The initialization functions might throw exception which is why
+   this function is not marked with __THROW.  */
+extern int pthread_once (pthread_once_t *__once_control,
+			 void (*__init_routine) (void));
+
+
+/* Functions for handling cancellation.  */
+
+/* Set cancelability state of current thread to STATE, returning old
+   state in *OLDSTATE if OLDSTATE is not NULL.  */
+extern int pthread_setcancelstate (int __state, int *__oldstate);
+
+/* Set cancellation state of current thread to TYPE, returning the old
+   type in *OLDTYPE if OLDTYPE is not NULL.  */
+extern int pthread_setcanceltype (int __type, int *__oldtype);
+
+/* Cancel THREAD immediately or at the next possibility.  */
+extern int pthread_cancel (pthread_t __cancelthread);
+
+/* Test for pending cancellation for the current thread and terminate
+   the thread as per pthread_exit(PTHREAD_CANCELED) if it has been
+   cancelled.  */
+extern void pthread_testcancel (void);
+
+
+/* Install a cleanup handler: ROUTINE will be called with arguments ARG
+   when the thread is cancelled or calls pthread_exit.  ROUTINE will also
+   be called with arguments ARG when the matching pthread_cleanup_pop
+   is executed with non-zero EXECUTE argument.
+   pthread_cleanup_push and pthread_cleanup_pop are macros and must always
+   be used in matching pairs at the same nesting level of braces. */
+
+#define pthread_cleanup_push(routine,arg) \
+  { struct _pthread_cleanup_buffer _buffer;				      \
+    _pthread_cleanup_push (&_buffer, (routine), (arg));
+
+extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
+				   void (*__routine) (void *),
+				   void *__arg) __THROW;
+
+/* Remove a cleanup handler installed by the matching pthread_cleanup_push.
+   If EXECUTE is non-zero, the handler function is called. */
+
+#define pthread_cleanup_pop(execute) \
+    _pthread_cleanup_pop (&_buffer, (execute)); }
+
+extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
+				  int __execute) __THROW;
+
+/* Install a cleanup handler as pthread_cleanup_push does, but also
+   saves the current cancellation type and set it to deferred cancellation.  */
+
+#ifdef __USE_GNU
+# define pthread_cleanup_push_defer_np(routine,arg) \
+  { struct _pthread_cleanup_buffer _buffer;				      \
+    _pthread_cleanup_push_defer (&_buffer, (routine), (arg));
+
+extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
+					 void (*__routine) (void *),
+					 void *__arg) __THROW;
+extern void __pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
+					  void (*__routine) (void *),
+					  void *__arg) __THROW;
+
+/* Remove a cleanup handler as pthread_cleanup_pop does, but also
+   restores the cancellation type that was in effect when the matching
+   pthread_cleanup_push_defer was called.  */
+
+# define pthread_cleanup_pop_restore_np(execute) \
+  _pthread_cleanup_pop_restore (&_buffer, (execute)); }
+
+extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
+					  int __execute) __THROW;
+extern void __pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
+					   int __execute) __THROW;
+#endif
+
+
+#if 0
+/* Not yet implemented in uClibc! */
+
+#ifdef __USE_XOPEN2K
+/* Get ID of CPU-time clock for thread THREAD_ID.  */
+extern int pthread_getcpuclockid (pthread_t __thread_id,
+				  clockid_t *__clock_id) __THROW;
+#endif
+#endif
+
+
+/* Functions for handling signals.  */
+#include <bits/sigthread.h>
+
+
+/* Functions for handling process creation and process execution.  */
+
+/* Install handlers to be called when a new process is created with FORK.
+   The PREPARE handler is called in the parent process just before performing
+   FORK. The PARENT handler is called in the parent process just after FORK.
+   The CHILD handler is called in the child process.  Each of the three
+   handlers can be NULL, meaning that no handler needs to be called at that
+   point.
+   PTHREAD_ATFORK can be called several times, in which case the PREPARE
+   handlers are called in LIFO order (last added with PTHREAD_ATFORK,
+   first called before FORK), and the PARENT and CHILD handlers are called
+   in FIFO (first added, first called).  */
+
+extern int pthread_atfork (void (*__prepare) (void),
+			   void (*__parent) (void),
+			   void (*__child) (void)) __THROW;
+
+/* Terminate all threads in the program except the calling process.
+   Should be called just before invoking one of the exec*() functions.  */
+
+extern void pthread_kill_other_threads_np (void) __THROW;
+
+__END_DECLS
+
+#endif	/* pthread.h */

+ 0 - 0
libpthread/linuxthreads/sysdeps/pthread/tls.h → libpthread/linuxthreads.old/sysdeps/pthread/tls.h


+ 81 - 0
libpthread/linuxthreads.old/sysdeps/sh/pt-machine.h

@@ -0,0 +1,81 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   SuperH version.
+   Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Niibe Yutaka <gniibe@m17n.org>.
+
+   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; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#include <features.h>
+
+#ifndef __ASSEMBLER__
+#ifndef PT_EI
+# define PT_EI __extern_always_inline
+#endif
+
+extern long int testandset (int *spinlock);
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  int ret;
+
+  __asm__ __volatile__(
+       "tas.b	@%1\n\t"
+       "movt	%0"
+       : "=r" (ret)
+       : "r" (spinlock)
+       : "memory", "cc");
+
+  return (ret == 0);
+}
+
+/* We want the OS to assign stack addresses.  */
+#define FLOATING_STACKS 1
+
+/* Maximum size of the stack if the rlimit is unlimited.  */
+#define ARCH_STACK_MAX_SIZE     32*1024*1024
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  stack_pointer
+register char * stack_pointer __asm__ ("r15");
+
+/* Return the thread descriptor for the current thread.  */
+struct _pthread_descr_struct;
+#define THREAD_SELF \
+  ({ struct _pthread_descr_struct *self; \
+      __asm__("stc gbr,%0" : "=r" (self)); self;})
+
+/* Initialize the thread-unique value.  */
+#define INIT_THREAD_SELF(descr, nr) \
+  ({ __asm__ __volatile__("ldc %0,gbr" : : "r" (descr));})
+
+/* Access to data in the thread descriptor is easy.  */
+#define THREAD_GETMEM(descr, member) \
+  ((void) sizeof (descr), THREAD_SELF->member)
+#define THREAD_GETMEM_NC(descr, member) \
+  ((void) sizeof (descr), THREAD_SELF->member)
+#define THREAD_SETMEM(descr, member, value) \
+  ((void) sizeof (descr), THREAD_SELF->member = (value))
+#define THREAD_SETMEM_NC(descr, member, value) \
+  ((void) sizeof (descr), THREAD_SELF->member = (value))
+#endif /* __ASSEMBLER__ */
+
+#endif /* pt-machine.h */

+ 116 - 0
libpthread/linuxthreads.old/sysdeps/sh/tls.h

@@ -0,0 +1,116 @@
+/* Definition for thread-local data handling.  linuxthreads/SH version.
+   Copyright (C) 2002, 2003, 2005 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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _TLS_H
+#define _TLS_H
+
+# include <pt-machine.h>
+
+#ifndef __ASSEMBLER__
+# include <stdbool.h>
+# include <stddef.h>
+# include <stdint.h>
+
+/* Type for the dtv.  */
+typedef union dtv
+{
+  size_t counter;
+  void *pointer;
+} dtv_t;
+
+
+typedef struct
+{
+  void *tcb;		/* Pointer to the TCB.  Not necessary the
+			   thread descriptor used by libpthread.  */
+  dtv_t *dtv;
+  void *self;		/* Pointer to the thread descriptor.  */
+} tcbhead_t;
+
+
+/* We can support TLS only if the floating-stack support is available.  */
+#if defined FLOATING_STACKS && defined HAVE_TLS_SUPPORT
+
+/* Get system call information.  */
+# include <sysdep.h>
+
+/* Signal that TLS support is available.  */
+//# define USE_TLS	1
+
+
+/* Get the thread descriptor definition.  */
+# include <linuxthreads/descr.h>
+
+/* This is the size of the initial TCB.  */
+# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
+
+/* Alignment requirements for the initial TCB.  */
+# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
+
+/* This is the size of the TCB.  */
+# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct)
+
+/* Alignment requirements for the TCB.  */
+# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
+
+/* The TLS blocks start right after the TCB.  */
+# 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) \
+  ({ struct _pthread_descr_struct *__descr;				      \
+     THREAD_SETMEM (__descr, p_header.data.dtvp, (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(descr, secondcall) \
+  ({									      \
+    void *_descr = (descr);						      \
+    int result;								      \
+    tcbhead_t *head = _descr;						      \
+									      \
+    head->tcb = _descr;							      \
+    /* For now the thread descriptor is at the same address.  */	      \
+    head->self = _descr;						      \
+									      \
+    __asm__ ("ldc %0,gbr" : : "r" (_descr));				      \
+									      \
+    0;									      \
+  })
+
+
+/* Return the address of the dtv for the current thread.  */
+# define THREAD_DTV() \
+  ({ struct _pthread_descr_struct *__descr;				      \
+     THREAD_GETMEM (__descr, p_header.data.dtvp); })
+
+#endif	/* FLOATING_STACKS && HAVE_TLS_SUPPORT */
+#endif /* __ASSEMBLER__ */
+
+#endif	/* tls.h */

+ 0 - 0
libpthread/linuxthreads/sysdeps/sh64/Makefile.arch → libpthread/linuxthreads.old/sysdeps/sh64/Makefile.arch


+ 0 - 0
libpthread/linuxthreads/sysdeps/sh64/pt-machine.c → libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.c


+ 0 - 0
libpthread/linuxthreads/sysdeps/sh64/pt-machine.h → libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.h


+ 82 - 0
libpthread/linuxthreads.old/sysdeps/sparc/pt-machine.h

@@ -0,0 +1,82 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   sparc version.
+   Copyright (C) 1996-1998, 2000-2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson <rth@tamu.edu>.
+
+   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; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#ifndef PT_EI
+# define PT_EI __extern_always_inline
+#endif
+
+extern long int testandset (int *spinlock);
+extern int __compare_and_swap (long int *p, long int oldval, long int newval);
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  int ret;
+
+  __asm__ __volatile__("ldstub %1,%0"
+	: "=r"(ret), "=m"(*spinlock)
+	: "m"(*spinlock));
+
+  return ret;
+}
+
+
+/* Memory barrier; default is to do nothing */
+#define MEMORY_BARRIER() __asm__ __volatile__("stbar" : : : "memory")
+
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  (stack_pointer + (2 * 64))
+register char *stack_pointer __asm__("%sp");
+
+
+/* Registers %g6 and %g7 are reserved by the ABI for "system use".
+   %g7 is specified in the TLS ABI as thread pointer -- we do the same.  */
+struct _pthread_descr_struct;
+register struct _pthread_descr_struct *__thread_self __asm__("%g7");
+
+/* Return the thread descriptor for the current thread.  */
+#define THREAD_SELF  __thread_self
+
+/* Initialize the thread-unique value.  */
+#define INIT_THREAD_SELF(descr, nr)  (__thread_self = (descr))
+
+/* Access to data in the thread descriptor is easy.  */
+#define THREAD_GETMEM(descr, member) \
+  ((void) sizeof (descr), THREAD_SELF->member)
+#define THREAD_GETMEM_NC(descr, member) \
+  ((void) sizeof (descr), THREAD_SELF->member)
+#define THREAD_SETMEM(descr, member, value) \
+  ((void) sizeof (descr), THREAD_SELF->member = (value))
+#define THREAD_SETMEM_NC(descr, member, value) \
+  ((void) sizeof (descr), THREAD_SELF->member = (value))
+
+/* We want the OS to assign stack addresses.  */
+#define FLOATING_STACKS 1
+
+/* Maximum size of the stack if the rlimit is unlimited.  */
+#define ARCH_STACK_MAX_SIZE     8*1024*1024
+
+#endif /* pt-machine.h */

+ 0 - 0
libpthread/linuxthreads/sysdeps/sparc/tcb-offsets.h → libpthread/linuxthreads.old/sysdeps/sparc/tcb-offsets.h


+ 0 - 0
libpthread/linuxthreads/sysdeps/v850/pt-machine.h → libpthread/linuxthreads.old/sysdeps/v850/pt-machine.h


+ 87 - 0
libpthread/linuxthreads.old/sysdeps/x86_64/pt-machine.h

@@ -0,0 +1,87 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   x86-64 version.
+   Copyright (C) 2001, 2002, 2003, 2004 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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#include <features.h>
+
+#ifndef __ASSEMBLER__
+# include <stddef.h>	/* For offsetof.  */
+# include <stdlib.h>	/* For abort().  */
+# include <asm/prctl.h>
+
+
+# ifndef PT_EI
+#  define PT_EI __extern_always_inline
+# endif
+
+extern long int testandset (int *);
+extern int __compare_and_swap (long int *, long int, long int);
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+# define CURRENT_STACK_FRAME  stack_pointer
+register char * stack_pointer __asm__ ("%rsp") __attribute_used__;
+
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *__spinlock)
+{
+  long int ret;
+
+  __asm__ __volatile__ (
+	"xchgl %k0, %1"
+	: "=r"(ret), "=m"(*__spinlock)
+	: "0"(1), "m"(*__spinlock)
+	: "memory");
+
+  return ret;
+}
+
+
+/* Compare-and-swap for semaphores.  */
+# define HAS_COMPARE_AND_SWAP
+
+PT_EI int
+__compare_and_swap (long int *__p, long int __oldval, long int __newval)
+{
+  char ret;
+  long int readval;
+
+  __asm__ __volatile__ ("lock; cmpxchgq %3, %1; sete %0"
+			: "=q" (ret), "=m" (*__p), "=a" (readval)
+			: "r" (__newval), "m" (*__p), "a" (__oldval)
+			: "memory");
+  return ret;
+}
+
+#endif /* !__ASSEMBLER__ */
+
+/* We want the OS to assign stack addresses.  */
+#define FLOATING_STACKS	1
+
+/* Maximum size of the stack if the rlimit is unlimited.  */
+#define ARCH_STACK_MAX_SIZE	32*1024*1024
+
+/* The ia32e really want some help to prevent overheating.  */
+#define BUSY_WAIT_NOP	__asm__ ("rep; nop")
+
+#endif /* pt-machine.h */

+ 133 - 0
libpthread/linuxthreads.old/sysdeps/x86_64/tls.h

@@ -0,0 +1,133 @@
+/* Definitions for thread-local data handling.  linuxthreads/x86-64 version.
+   Copyright (C) 2002, 2005 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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _TLS_H
+#define _TLS_H
+
+#ifndef __ASSEMBLER__
+
+# include <pt-machine.h>
+# include <stdbool.h>
+# include <stddef.h>
+
+/* Type for the dtv.  */
+typedef union dtv
+{
+  size_t counter;
+  struct
+  {
+    void *val;
+    bool is_static;
+  } pointer;
+} dtv_t;
+
+
+typedef struct
+{
+  void *tcb;		/* Pointer to the TCB.  Not necessary the
+			   thread descriptor used by libpthread.  */
+  dtv_t *dtv;
+  void *self;		/* Pointer to the thread descriptor.  */
+  int multiple_threads;
+} tcbhead_t;
+
+#else /* __ASSEMBLER__ */
+# include <tcb-offsets.h>
+#endif
+
+
+#ifdef HAVE_TLS_SUPPORT
+
+/* Signal that TLS support is available.  */
+# define USE_TLS	1
+
+# ifndef __ASSEMBLER__
+/* Get system call information.  */
+#  include <sysdep.h>
+
+/* Get the thread descriptor definition.  */
+#  include <linuxthreads/descr.h>
+
+/* This is the size of the initial TCB.  */
+#  define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
+
+/* Alignment requirements for the initial TCB.  */
+#  define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
+
+/* This is the size of the TCB.  */
+#  define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct)
+
+/* Alignment requirements for the TCB.  */
+#  define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
+
+/* The TCB can have any size and the memory following the address the
+   thread pointer points to is unspecified.  Allocate the TCB there.  */
+#  define TLS_TCB_AT_TP	1
+
+
+/* Install the dtv pointer.  The pointer passed is to the element with
+   index -1 which contain the length.  */
+#  define INSTALL_DTV(descr, dtvp) \
+  ((tcbhead_t *) (descr))->dtv = (dtvp) + 1
+
+/* Install new dtv for current thread.  */
+#  define INSTALL_NEW_DTV(dtv) \
+  ({ struct _pthread_descr_struct *__descr;				      \
+     THREAD_SETMEM (__descr, p_header.data.dtvp, (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(descr, secondcall)					      \
+  ({									      \
+    void *_descr = (descr);						      \
+    tcbhead_t *head = _descr;						      \
+    long int _result;							      \
+									      \
+    head->tcb = _descr;							      \
+    /* For now the thread descriptor is at the same address.  */	      \
+    head->self = _descr;						      \
+									      \
+    __asm__ __volatile__ ("syscall"						      \
+		  : "=a" (_result)					      \
+		  : "0" ((unsigned long int) __NR_arch_prctl),		      \
+		    "D" ((unsigned long int) ARCH_SET_FS),		      \
+		    "S" (_descr)					      \
+		  : "memory", "cc", "r11", "cx");			      \
+									      \
+    _result ? "cannot set %fs base address for thread-local storage" : 0;     \
+  })
+
+/* Indicate that dynamic linker shouldn't try to initialize TLS even
+   when no PT_TLS segments are found in the program and libraries
+   it is linked against.  */
+#  define TLS_INIT_TP_EXPENSIVE 1
+
+/* Return the address of the dtv for the current thread.  */
+#  define THREAD_DTV() \
+  ({ struct _pthread_descr_struct *__descr;				      \
+     THREAD_GETMEM (__descr, p_header.data.dtvp); })
+
+# endif	/* HAVE_TLS_SUPPORT */
+#endif /* __ASSEMBLER__ */
+
+#endif	/* tls.h */

+ 0 - 0
libpthread/linuxthreads/sysdeps/xtensa/pt-machine.h → libpthread/linuxthreads.old/sysdeps/xtensa/pt-machine.h


+ 0 - 0
libpthread/linuxthreads/wrapsyscall.c → libpthread/linuxthreads.old/wrapsyscall.c


+ 1 - 0
libpthread/linuxthreads.old_db/Banner

@@ -0,0 +1 @@
+libthread_db work sponsored by Alpha Processor Inc

+ 13 - 0
libpthread/linuxthreads.old_db/Makefile

@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../
+top_builddir=../../
+include $(top_builddir)Rules.mak
+all: libs
+include Makefile.in
+include $(top_srcdir)Makerules

+ 78 - 0
libpthread/linuxthreads.old_db/Makefile.in

@@ -0,0 +1,78 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libpthread/linuxthreads.old_db
+
+# Get the thread include dependencies and shared object name
+CFLAGS-libpthread/linuxthreads.old_db := -DNOT_IN_libc -DLIBPTHREAD_SO="\"libpthread.so.$(ABI_VERSION)\""
+
+LDFLAGS-libthread_db.so := $(LDFLAGS_NOSTRIP) $(if $(call check_ld,--warn-unresolved-symbols),-Wl$(comma)--warn-unresolved-symbols)
+ifeq ($(DOSTRIP),y)
+LDFLAGS-libthread_db.so += -Wl,-s
+endif
+
+LIBS-libthread_db.so := $(LIBS)
+
+libthread_db_FULL_NAME := libthread_db-$(VERSION).so
+
+libthread_db_DIR := $(top_srcdir)libpthread/linuxthreads.old_db
+libthread_db_OUT := $(top_builddir)libpthread/linuxthreads.old_db
+
+libthread_db_SRC := $(wildcard $(libthread_db_DIR)/*.c)
+
+libthread_db_OBJ := $(patsubst $(libthread_db_DIR)/%.c,$(libthread_db_OUT)/%.o,$(libthread_db_SRC))
+
+libthread_db-so-y := $(libthread_db_OBJ:.o=.os)
+ifeq ($(DOPIC),y)
+libthread_db-a-y  := $(libthread_db-so-y)
+else
+libthread_db-a-y  := $(libthread_db_OBJ)
+endif
+
+lib-a-$(PTHREADS_DEBUG_SUPPORT) += $(top_builddir)lib/libthread_db.a
+lib-so-$(PTHREADS_DEBUG_SUPPORT) += $(top_builddir)lib/libthread_db.so
+
+#ifeq ($(DOMULTI),n)
+ifeq ($(DOPIC),y)
+$(top_builddir)lib/libthread_db.so: $(top_builddir)lib/libthread_db.a $(libc.depend)
+else
+$(top_builddir)lib/libthread_db.so: $(libthread_db_OUT)/libthread_db_so.a $(libc.depend)
+endif
+	$(call link.so,$(libthread_db_FULL_NAME),1)
+#else
+#$(top_builddir)lib/libthread_db.so: $(libthread_db_OUT)/libthread_db.oS | $(libc.depend)
+#	$(call linkm.so,$(libthread_db_FULL_NAME),1)
+#endif
+
+$(libthread_db_OUT)/libthread_db_so.a: $(libthread_db-so-y)
+	$(Q)$(RM) $@
+	$(do_ar)
+
+$(libthread_db_OUT)/libthread_db.oS: $(libthread_db_SRC)
+	$(Q)$(RM) $@
+	$(compile-m)
+
+$(top_builddir)lib/libthread_db.a: $(libthread_db-a-y)
+	$(Q)$(INSTALL) -d $(dir $@)
+	$(Q)$(RM) $@
+	$(do_ar)
+
+$(top_builddir)include/thread_db.h:
+	$(do_ln) $(call rel_srcdir)$(PTDIR)_db/$(@F) $@
+
+linuxthreads_db_headers := $(top_builddir)include/thread_db.h
+$(linuxthreads_db_headers): $(wildcard $(addprefix $(top_builddir)include/config/linuxthreads/,old.h new.h))
+headers-$(PTHREADS_DEBUG_SUPPORT) += $(linuxthreads_db_headers)
+
+objclean-y += CLEAN_libpthread/linuxthreads.old_db
+headers_clean-y += HEADERCLEAN_libpthread/linuxthreads.old_db
+
+HEADERCLEAN_libpthread/linuxthreads.old_db:
+	$(do_rm) $(linuxthreads_db_headers)
+
+CLEAN_libpthread/linuxthreads.old_db:
+	$(do_rm) $(addprefix $(libthread_db_OUT)/*., o os oS a)

+ 24 - 0
libpthread/linuxthreads.old_db/Versions

@@ -0,0 +1,24 @@
+libthread_db {
+  GLIBC_2.1.3 {
+    # t*
+    td_init; td_log; td_ta_clear_event; td_ta_delete; td_ta_enable_stats;
+    td_ta_event_addr; td_ta_event_getmsg; td_ta_get_nthreads; td_ta_get_ph;
+    td_ta_get_stats; td_ta_map_id2thr; td_ta_map_lwp2thr; td_ta_new;
+    td_ta_reset_stats; td_ta_set_event; td_ta_setconcurrency;
+    td_ta_thr_iter; td_ta_tsd_iter; td_thr_clear_event; td_thr_dbresume;
+    td_thr_dbsuspend; td_thr_event_enable; td_thr_event_getmsg;
+    td_thr_get_info; td_thr_getfpregs; td_thr_getgregs; td_thr_getxregs;
+    td_thr_getxregsize; td_thr_set_event; td_thr_setfpregs; td_thr_setgregs;
+    td_thr_setprio; td_thr_setsigpending; td_thr_setxregs; td_thr_sigsetmask;
+    td_thr_tsd; td_thr_validate;
+  }
+  GLIBC_2.2.3 {
+    td_symbol_list;
+  }
+  GLIBC_2.3 {
+    td_thr_tls_get_addr;
+  }
+  GLIBC_2.3.3 {
+    td_thr_tlsbase;
+  }
+}

+ 69 - 0
libpthread/linuxthreads.old_db/proc_service.h

@@ -0,0 +1,69 @@
+/* Copyright (C) 1999 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, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* The definitions in this file must correspond to those in the debugger.  */
+#include <sys/procfs.h>
+
+typedef enum
+{
+  PS_OK,          /* generic "call succeeded" */
+  PS_ERR,         /* generic. */
+  PS_BADPID,      /* bad process handle */
+  PS_BADLID,      /* bad lwp identifier */
+  PS_BADADDR,     /* bad address */
+  PS_NOSYM,       /* p_lookup() could not find given symbol */
+        PS_NOFREGS
+  /*
+   * FPU register set not available for given
+   * lwp
+   */
+}       ps_err_e;
+
+
+struct ps_prochandle;		/* user defined. */
+
+
+extern ps_err_e ps_pdread(struct ps_prochandle *,
+                        psaddr_t, void *, size_t);
+extern ps_err_e ps_pdwrite(struct ps_prochandle *,
+                        psaddr_t, const void *, size_t);
+extern ps_err_e ps_ptread(struct ps_prochandle *,
+                        psaddr_t, void *, size_t);
+extern ps_err_e ps_ptwrite(struct ps_prochandle *,
+                        psaddr_t, const void *, size_t);
+
+extern ps_err_e ps_pglobal_lookup(struct ps_prochandle *,
+        const char *object_name, const char *sym_name, psaddr_t *sym_addr);
+
+
+extern ps_err_e ps_lgetregs(struct ps_prochandle *,
+                        lwpid_t, prgregset_t);
+extern ps_err_e ps_lsetregs(struct ps_prochandle *,
+                        lwpid_t, const prgregset_t);
+extern ps_err_e ps_lgetfpregs(struct ps_prochandle *,
+                        lwpid_t, prfpregset_t *);
+extern ps_err_e ps_lsetfpregs(struct ps_prochandle *,
+                        lwpid_t, const prfpregset_t *);
+
+extern pid_t ps_getpid (struct ps_prochandle *);
+
+
+extern ps_err_e ps_pstop (const struct ps_prochandle *);
+extern ps_err_e ps_pcontinue (const struct ps_prochandle *);
+
+extern ps_err_e ps_lstop (const struct ps_prochandle *, lwpid_t);
+extern ps_err_e ps_lcontinue (const struct ps_prochandle *, lwpid_t);

+ 32 - 0
libpthread/linuxthreads.old_db/td_init.c

@@ -0,0 +1,32 @@
+/* Initialization function of thread debugger support library.
+   Copyright (C) 1999, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
+
+   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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "thread_dbP.h"
+
+#ifndef NDEBUG
+int __td_debug;
+#endif
+
+td_err_e
+td_init (void)
+{
+  /* XXX We have to figure out what has to be done.  */
+  LOG ("td_init");
+  return TD_OK;
+}

+ 31 - 0
libpthread/linuxthreads.old_db/td_log.c

@@ -0,0 +1,31 @@
+/* Noop, left for historical reasons.
+   Copyright (C) 1999, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
+
+   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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_log (void)
+{
+  /* This interface is deprecated in the Sun interface.  We provide it
+     for compatibility but don't do anything ourself.  We might in
+     future do some logging if this seems reasonable.  */
+  LOG ("td_log");
+  return TD_OK;
+}

+ 60 - 0
libpthread/linuxthreads.old_db/td_symbol_list.c

@@ -0,0 +1,60 @@
+/* Return list of symbols the library can request.
+   Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 2001.
+
+   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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include "thread_dbP.h"
+
+#ifdef HAVE_ASM_GLOBAL_DOT_NAME
+# define DOT "."		/* PPC64 requires . prefix on code symbols.  */
+#else
+# define DOT			/* No prefix.  */
+#endif
+
+static const char *symbol_list_arr[] =
+{
+  [PTHREAD_THREADS_EVENTS] = "__pthread_threads_events",
+  [PTHREAD_LAST_EVENT] = "__pthread_last_event",
+  [PTHREAD_HANDLES_NUM] = "__pthread_handles_num",
+  [PTHREAD_HANDLES] = "__pthread_handles",
+  [PTHREAD_KEYS] = "pthread_keys",
+  [LINUXTHREADS_PTHREAD_THREADS_MAX] = "__linuxthreads_pthread_threads_max",
+  [LINUXTHREADS_PTHREAD_KEYS_MAX] = "__linuxthreads_pthread_keys_max",
+  [LINUXTHREADS_PTHREAD_SIZEOF_DESCR] = "__linuxthreads_pthread_sizeof_descr",
+  [LINUXTHREADS_CREATE_EVENT] = DOT "__linuxthreads_create_event",
+  [LINUXTHREADS_DEATH_EVENT] = DOT "__linuxthreads_death_event",
+  [LINUXTHREADS_REAP_EVENT] = DOT "__linuxthreads_reap_event",
+  [LINUXTHREADS_INITIAL_REPORT_EVENTS] = "__linuxthreads_initial_report_events",
+  [LINUXTHREADS_VERSION] = "__linuxthreads_version",
+  [NUM_MESSAGES] = NULL
+};
+
+
+const char **
+td_symbol_list (void)
+{
+  return symbol_list_arr;
+}
+
+
+int
+td_lookup (struct ps_prochandle *ps, int idx, psaddr_t *sym_addr)
+{
+  assert (idx >= 0 && idx < NUM_MESSAGES);
+  return ps_pglobal_lookup (ps, LIBPTHREAD_SO, symbol_list_arr[idx], sym_addr);
+}

+ 50 - 0
libpthread/linuxthreads.old_db/td_ta_clear_event.c

@@ -0,0 +1,50 @@
+/* Globally disable events.
+   Copyright (C) 1999, 2001, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
+
+   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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_ta_clear_event(const td_thragent_t *ta,td_thr_events_t *event)
+{
+  td_thr_events_t old_event;
+  int i;
+
+  LOG ("td_ta_clear_event");
+
+  /* Test whether the TA parameter is ok.  */
+  if (! ta_ok (ta))
+    return TD_BADTA;
+
+  /* Write the new value into the thread data structure.  */
+  if (ps_pdread (ta->ph, ta->pthread_threads_eventsp,
+		 &old_event, sizeof (td_thr_events_t)) != PS_OK)
+    return TD_ERR;	/* XXX Other error value?  */
+
+  /* Remove the set bits in.  */
+  for (i = 0; i < TD_EVENTSIZE; ++i)
+    old_event.event_bits[i] &= ~event->event_bits[i];
+
+  /* Write the new value into the thread data structure.  */
+  if (ps_pdwrite (ta->ph, ta->pthread_threads_eventsp,
+		  &old_event, sizeof (td_thr_events_t)) != PS_OK)
+    return TD_ERR;	/* XXX Other error value?  */
+
+  return TD_OK;
+}

+ 57 - 0
libpthread/linuxthreads.old_db/td_ta_delete.c

@@ -0,0 +1,57 @@
+/* Detach to target process.
+   Copyright (C) 1999, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
+
+   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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_ta_delete (td_thragent_t *ta)
+{
+  LOG ("td_ta_delete");
+
+  /* Safety check.  */
+  if (ta == NULL || __td_agent_list == NULL)
+    return TD_BADTA;
+
+  /* Remove the handle from the list.  */
+  if (ta == __td_agent_list->ta)
+    /* It's the first element of the list.  */
+    __td_agent_list = __td_agent_list->next;
+  else
+    {
+      /* We have to search for it.  */
+      struct agent_list *runp = __td_agent_list;
+
+      while (runp->next != NULL && runp->next->ta != ta)
+	runp = runp->next;
+
+      if (runp->next == NULL)
+	/* It's not a valid descriptor since it is not in the list.  */
+	return TD_BADTA;
+
+      runp->next = runp->next->next;
+    }
+
+  /* The handle was allocated in `td_ta_new'.  */
+  free (ta);
+
+  return TD_OK;
+}

+ 34 - 0
libpthread/linuxthreads.old_db/td_ta_enable_stats.c

@@ -0,0 +1,34 @@
+/* Enable collection of statistics for process.
+   Copyright (C) 1999, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
+
+   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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_ta_enable_stats (const td_thragent_t *ta, int enable)
+{
+  /* XXX We have to figure out what has to be done.  */
+  LOG ("td_ta_enable_stats");
+
+  /* Test whether the TA parameter is ok.  */
+  if (! ta_ok (ta))
+    return TD_BADTA;
+
+  return TD_OK;
+}

+ 72 - 0
libpthread/linuxthreads.old_db/td_ta_event_addr.c

@@ -0,0 +1,72 @@
+/* Get event address.
+   Copyright (C) 1999, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
+
+   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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_ta_event_addr (const td_thragent_t *ta, td_event_e event, td_notify_t *addr)
+{
+  td_err_e res = TD_NOEVENT;
+  int idx = -1;
+
+  LOG ("td_ta_event_addr");
+
+  /* Test whether the TA parameter is ok.  */
+  if (! ta_ok (ta))
+    return TD_BADTA;
+
+  switch (event)
+    {
+    case TD_CREATE:
+      idx = LINUXTHREADS_CREATE_EVENT;
+      break;
+
+    case TD_DEATH:
+      idx = LINUXTHREADS_DEATH_EVENT;
+      break;
+
+    case TD_REAP:
+      idx = LINUXTHREADS_REAP_EVENT;
+      break;
+
+    default:
+      /* Event cannot be handled.  */
+      break;
+    }
+
+  /* Now get the address.  */
+  if (idx != -1)
+    {
+      psaddr_t taddr;
+
+      if (td_lookup (ta->ph, idx, &taddr) == PS_OK)
+	{
+	  /* Success, we got the address.  */
+	  addr->type = NOTIFY_BPT;
+	  addr->u.bptaddr = taddr;
+
+	  res = TD_OK;
+	}
+      else
+	res = TD_ERR;
+    }
+
+  return res;
+}

+ 127 - 0
libpthread/linuxthreads.old_db/td_ta_event_getmsg.c

@@ -0,0 +1,127 @@
+/* Retrieve event.
+   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
+
+   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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stddef.h>
+#include <string.h>
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_ta_event_getmsg (const td_thragent_t *ta, td_event_msg_t *msg)
+{
+  /* XXX I cannot think of another way but using a static variable.  */
+  static td_thrhandle_t th;
+  td_eventbuf_t event;
+  psaddr_t addr;
+
+  LOG ("td_ta_event_getmsg");
+
+  /* Test whether the TA parameter is ok.  */
+  if (! ta_ok (ta))
+    return TD_BADTA;
+
+  /* Get the pointer to the thread descriptor with the last event.  */
+  if (ps_pdread (ta->ph, ta->pthread_last_event,
+		 &addr, sizeof (void *)) != PS_OK)
+    return TD_ERR;	/* XXX Other error value?  */
+
+  /* If the pointer is NULL no event occurred.  */
+  if (addr == 0)
+    return TD_NOMSG;
+
+  /* Read the even structure from the target.  */
+  if (ps_pdread (ta->ph,
+		 ((char *) addr
+		  + offsetof (struct _pthread_descr_struct, p_eventbuf)),
+		 &event, sizeof (td_eventbuf_t)) != PS_OK)
+    return TD_ERR;	/* XXX Other error value?  */
+
+  /* Check whether an event occurred.  */
+  if (event.eventnum == TD_EVENT_NONE)
+    {
+      /* Oh well, this means the last event was already read.  So
+	 we have to look for any other event.  */
+      struct pthread_handle_struct handles[ta->pthread_threads_max];
+      int num;
+      int i;
+
+      /* Read the number of currently active threads.  */
+      if (ps_pdread (ta->ph, ta->pthread_handles_num, &num, sizeof (int))
+	  != PS_OK)
+	return TD_ERR;	/* XXX Other error value?  */
+
+      /* Now read the handles.  */
+      if (ps_pdread (ta->ph, ta->handles, handles,
+		     ta->pthread_threads_max * sizeof (handles[0])) != PS_OK)
+	return TD_ERR;	/* XXX Other error value?  */
+
+      for (i = 0; i < ta->pthread_threads_max && num > 0; ++i)
+	{
+	  if (handles[i].h_descr == NULL)
+	    /* No entry here.  */
+	    continue;
+
+	  /* First count this active thread.  */
+	  --num;
+
+	  if (handles[i].h_descr == addr)
+	    /* We already handled this.  */
+	    continue;
+
+	  /* Read the event data for this thread.  */
+	  if (ps_pdread (ta->ph,
+			 ((char *) handles[i].h_descr
+			  + offsetof (struct _pthread_descr_struct,
+				      p_eventbuf)),
+			 &event, sizeof (td_eventbuf_t)) != PS_OK)
+	    return TD_ERR;
+
+	  if (event.eventnum != TD_EVENT_NONE)
+	    {
+	      /* We found a thread with an unreported event.  */
+	      addr = handles[i].h_descr;
+	      break;
+	    }
+	}
+
+      /* If we haven't found any other event signal this to the user.  */
+      if (event.eventnum == TD_EVENT_NONE)
+	return TD_NOMSG;
+    }
+
+  /* Generate the thread descriptor.  */
+  th.th_ta_p = (td_thragent_t *) ta;
+  th.th_unique = addr;
+
+  /* Fill the user's data structure.  */
+  msg->event = event.eventnum;
+  msg->th_p = &th;
+  msg->msg.data = (uintptr_t) event.eventdata;
+
+  /* And clear the event message in the target.  */
+  memset (&event, '\0', sizeof (td_eventbuf_t));
+  if (ps_pdwrite (ta->ph,
+		  ((char *) addr
+		   + offsetof (struct _pthread_descr_struct, p_eventbuf)),
+		  &event, sizeof (td_eventbuf_t)) != PS_OK)
+    return TD_ERR;	/* XXX Other error value?  */
+
+  return TD_OK;
+}

+ 41 - 0
libpthread/linuxthreads.old_db/td_ta_get_nthreads.c

@@ -0,0 +1,41 @@
+/* Get the number of threads in the process.
+   Copyright (C) 1999, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
+
+   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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "thread_dbP.h"
+
+td_err_e
+td_ta_get_nthreads (const td_thragent_t *ta, int *np)
+{
+  psaddr_t addr;
+
+  LOG ("td_ta_get_nthreads");
+
+  /* Test whether the TA parameter is ok.  */
+  if (! ta_ok (ta))
+    return TD_BADTA;
+
+  /* Access the variable `__pthread_handles_num'.  */
+  if (td_lookup (ta->ph, PTHREAD_HANDLES_NUM, &addr) != PS_OK)
+     return TD_ERR;	/* XXX Other error value?  */
+
+  if (ps_pdread (ta->ph, addr, np, sizeof (int)) != PS_OK)
+     return TD_ERR;	/* XXX Other error value?  */
+
+  return TD_OK;
+}

+ 35 - 0
libpthread/linuxthreads.old_db/td_ta_get_ph.c

@@ -0,0 +1,35 @@
+/* Get external process handle.
+   Copyright (C) 1999, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
+
+   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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_ta_get_ph (const td_thragent_t *ta, struct ps_prochandle **ph)
+{
+  LOG ("td_ta_get_ph");
+
+  /* Test whether the TA parameter is ok.  */
+  if (! ta_ok (ta))
+    return TD_BADTA;
+
+  *ph = ta->ph;
+
+  return TD_OK;
+}

+ 34 - 0
libpthread/linuxthreads.old_db/td_ta_get_stats.c

@@ -0,0 +1,34 @@
+/* Retrieve statistics for process.
+   Copyright (C) 1999, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
+
+   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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_ta_get_stats (const td_thragent_t *ta, td_ta_stats_t *statsp)
+{
+  /* XXX We have to figure out what has to be done.  */
+  LOG ("td_ta_get_stats");
+
+  /* Test whether the TA parameter is ok.  */
+  if (! ta_ok (ta))
+    return TD_BADTA;
+
+  return TD_OK;
+}

+ 77 - 0
libpthread/linuxthreads.old_db/td_ta_map_id2thr.c

@@ -0,0 +1,77 @@
+/* Map thread ID to thread handle.
+   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
+
+   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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_ta_map_id2thr (const td_thragent_t *ta, pthread_t pt, td_thrhandle_t *th)
+{
+  struct pthread_handle_struct phc;
+  struct _pthread_descr_struct pds;
+  int pthread_threads_max;
+
+  LOG ("td_ta_map_id2thr");
+
+  /* Test whether the TA parameter is ok.  */
+  if (! ta_ok (ta))
+    return TD_BADTA;
+
+  /* Make the following expression a bit smaller.  */
+  pthread_threads_max = ta->pthread_threads_max;
+
+  /* We can compute the entry in the handle array we want.  */
+  if (ps_pdread (ta->ph, ta->handles + pt % pthread_threads_max, &phc,
+		 sizeof (struct pthread_handle_struct)) != PS_OK)
+    return TD_ERR;	/* XXX Other error value?  */
+
+  /* Test whether this entry is in use.  */
+  if (phc.h_descr == NULL)
+    {
+      if (pt % pthread_threads_max == 0)
+	{
+	  /* The initial thread always exists but the thread library
+	     might not yet be initialized.  */
+	  th->th_ta_p = (td_thragent_t *) ta;
+	  th->th_unique = NULL;
+
+	  return TD_OK;
+	}
+
+      return TD_BADTH;
+    }
+
+  /* Next test: get the descriptor to see whether this is not an old
+     thread handle.  */
+  if (ps_pdread (ta->ph, phc.h_descr, &pds,
+		 sizeof (struct _pthread_descr_struct)) != PS_OK)
+    return TD_ERR;	/* XXX Other error value?  */
+
+  if (pds.p_tid != pt)
+    return TD_BADTH;
+
+  if (pds.p_terminated != 0)
+    return TD_NOTHR;
+
+  /* Create the `td_thrhandle_t' object.  */
+  th->th_ta_p = (td_thragent_t *) ta;
+  th->th_unique = phc.h_descr;
+
+  return TD_OK;
+}

Some files were not shown because too many files changed in this diff