This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix IA-64 (take 2)


On Fri, Dec 20, 2002 at 05:55:11PM -0800, David Mosberger wrote:
> The unwind info for functions generated by this macro will be all wrong.

Thanks David.
Here is another version of the patch. This time it doesn't use
.previous and hopefully incorporates all the other things as well
(checked briefly with readelf -u). Passed make check on IA-64.
Also, I've included sparc32 and sparc64 bits too.

2002-12-22  Jakub Jelinek  <jakub@redhat.com>

	* sysdeps/unix/sysv/linux/ia64/sysdep.h (INLINE_SYSCALL,
	INTERNAL_SYSCALL, INTERNAL_SYSCALL_ERROR_P, INTERNAL_SYSCALL_ERROR):
	Define. Patch by Richard Henderson and Jes Sorensen.
	(PSEUDO): Remove unnecessary ;;.
	* elf/rtld.c (dl_main): Initialize TLS even if no PT_TLS segments
	are found unless TLS_INIT_TP_EXPENSIVE.  Use NONTLS_INIT_TP.
	* sysdeps/generic/libc-tls.c (__libc_setup_tls): Use NONTLS_INIT_TP
	if not initializing thread pointer.
	[!USE_TLS && NONTLS_INIT_TP] (__pthread_initialize_minimal): New.
	* sysdeps/generic/libc-start.c (__pthread_initialize_minimal): Don't
	make it weak also if NONTLS_INIT_TP.
	* sysdeps/unix/common/pause.c: Handle cancellation.
	* sysdeps/unix/sysv/linux/sparc/sparc32/sysdep.h [DONT_LOAD_G1]
	(LOADSYSCALL): Remove.
	(SYSCALL_ERROR_HANDLER_ENTRY): Define.
	(SYSCALL_ERROR_HANDLER): Use it.
	(PSEUDO): Don't jump around error handler.
	* sysdeps/unix/sysv/linux/sparc/sparc32/pipe.S (__libc_pipe): Don't
	jump around error handler.
	* sysdeps/unix/sysv/linux/sparc/sparc32/syscall.S (syscall): Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/socket.S (__socket): Branch
	to __syscall_error_handler on failure.
	* sysdeps/unix/sysv/linux/sparc/sparc64/sysdep.h [DONT_LOAD_G1]
	(LOADSYSCALL): Remove.
	(SYSCALL_ERROR_HANDLER_ENTRY): Define.
	(SYSCALL_ERROR_HANDLER): Use it.
	(PSEUDO): Don't jump around error handler.
	* sysdeps/unix/sysv/linux/sparc/sparc64/pipe.S (__libc_pipe): Don't
	jump around error handler.
	* sysdeps/unix/sysv/linux/sparc/sparc64/syscall.S (syscall): Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/socket.S (__socket): Branch
	to __syscall_error_handler on failure.

linuxthreads/
	* libc_pthread_init.c: Include stdlib.h.
	* sysdeps/i386/tls.h (tcbhead_t): Add multiple_threads member.
	(TLS_INIT_TP_EXPENSIVE): Define.
	* sysdeps/pthread/bits/libc-lock.h (__libc_maybe_call,
	__libc_maybe_call2): In _LIBC check SHARED define.
	* sysdeps/ia64/tls.h: New file.
	* sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h: New file.
	* sysdeps/unix/sysv/linux/ia64/Makefile: New file.
	* sysdeps/x86_64/tls.h (TLS_INIT_TP_EXPENSIVE): Define.
	* sysdeps/sparc/sparc32/tls.h: New file.
	* sysdeps/sparc/sparc64/tls.h: New file.
	* sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h: New file.
	* sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h: New file.
	* Makefile (tests): Add tst-cancel[1-6].
	(tests-reverse): Add tst-cancel5.
	Link libc.so before libpthread.so for tests-reverse.
	* tst-cancel1.c: New file.
	* tst-cancel2.c: New file.
	* tst-cancel3.c: New file.
	* tst-cancel4.c: New file.
	* tst-cancel5.c: New file.
	* tst-cancel6.c: New file.

nptl/
	* Makefile (tests-reverse): Use $(objpfx)../libc.so instead of
	$(common-objpfx)libc.so.
	* tst-cancel4.c (tf_write, tf_writev): Increase buf sizes so that
	it is bigger than pipe buffer size even on arches with bigger
	page size.
	(tf_usleep): Cast usleep argument to useconds_t to avoid warnings.

--- libc/elf/rtld.c.jj	2002-12-20 13:34:41.000000000 +0100
+++ libc/elf/rtld.c	2002-12-23 00:04:24.000000000 +0100
@@ -1150,6 +1150,10 @@ of this helper program; chances are you 
     /* Assign a module ID.  */
     GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
 
+# ifndef TLS_INIT_TP_EXPENSIVE
+#  define TLS_INIT_TP_EXPENSIVE 0
+# endif
+
   /* We do not initialize any of the TLS functionality unless any of the
      initial modules uses TLS.  This makes dynamic loading of modules with
      TLS impossible, but to support it requires either eagerly doing setup
@@ -1157,7 +1161,7 @@ of this helper program; chances are you 
      an old kernel that can't perform TLS_INIT_TP, even if no TLS is ever
      used.  Trying to do it lazily is too hairy to try when there could be
      multiple threads (from a non-TLS-using libpthread).  */
-  if (GL(dl_tls_max_dtv_idx) > 0)
+  if (GL(dl_tls_max_dtv_idx) > 0 || !TLS_INIT_TP_EXPENSIVE)
     {
       struct link_map *l;
       size_t nelem;
@@ -1565,8 +1569,12 @@ cannot allocate TLS data structures for 
      we need it in the memory handling later.  */
   GL(dl_initial_searchlist) = *GL(dl_main_searchlist);
 
+#ifndef NONTLS_INIT_TP
+# define NONTLS_INIT_TP do { } while (0)
+#endif
+
 #ifdef USE_TLS
-  if (GL(dl_tls_max_dtv_idx) > 0 || USE___THREAD)
+  if (GL(dl_tls_max_dtv_idx) > 0 || USE___THREAD || !TLS_INIT_TP_EXPENSIVE)
     {
       /* Now that we have completed relocation, the initializer data
 	 for the TLS blocks has its final values and we can copy them
@@ -1579,7 +1587,9 @@ cannot allocate TLS data structures for 
       if (__builtin_expect (lossage != NULL, 0))
 	_dl_fatal_printf ("cannot set up thread-local storage: %s\n", lossage);
     }
+  else
 #endif
+    NONTLS_INIT_TP;
 
   {
     /* Initialize _r_debug.  */
--- libc/linuxthreads/libc_pthread_init.c.jj	2002-12-18 02:15:55.000000000 +0100
+++ libc/linuxthreads/libc_pthread_init.c	2002-12-20 17:23:42.000000000 +0100
@@ -17,9 +17,10 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#include <locale.h>
+#include <stdlib.h>
 #include <string.h>
 #include <tls.h>
-#include <locale.h>
 #include "internals.h"
 #include <sysdep-cancel.h>
 
--- libc/linuxthreads/sysdeps/i386/tls.h.jj	2002-12-10 15:08:36.000000000 +0100
+++ libc/linuxthreads/sysdeps/i386/tls.h	2002-12-20 16:00:18.000000000 +0100
@@ -39,6 +39,7 @@ typedef struct
 			   thread descriptor used by libpthread.  */
   dtv_t *dtv;
   void *self;		/* Pointer to the thread descriptor.  */
+  int multiple_threads;
 } tcbhead_t;
 #endif
 
@@ -192,6 +193,10 @@ TLS_DO_MODIFY_LDT_KERNEL_CHECK(						   
     TLS_SETUP_GS_SEGMENT (_descr, secondcall);				      \
   })
 
+/* 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() \
--- libc/linuxthreads/sysdeps/pthread/bits/libc-lock.h.jj	2002-12-20 13:35:37.000000000 +0100
+++ libc/linuxthreads/sysdeps/pthread/bits/libc-lock.h	2002-12-20 17:33:13.000000000 +0100
@@ -97,7 +97,7 @@ typedef pthread_key_t __libc_key_t;
 #if defined _LIBC && defined IS_IN_libpthread
 # define __libc_maybe_call(FUNC, ARGS, ELSE) FUNC ARGS
 #else
-# ifdef __PIC__
+# if defined __PIC__ || (defined _LIBC && defined SHARED)
 #  define __libc_maybe_call(FUNC, ARGS, ELSE) \
   (__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \
                     _fn != NULL ? (*_fn) ARGS : ELSE; }))
@@ -106,7 +106,7 @@ typedef pthread_key_t __libc_key_t;
   (FUNC != NULL ? FUNC ARGS : ELSE)
 # endif
 #endif
-#if defined _LIBC && !defined NOT_IN_libc && defined __PIC__
+#if defined _LIBC && !defined NOT_IN_libc && defined SHARED
 # define __libc_maybe_call2(FUNC, ARGS, ELSE) \
   ({__libc_pthread_functions.ptr_##FUNC != NULL \
     ? __libc_pthread_functions.ptr_##FUNC ARGS : ELSE; })
--- libc/linuxthreads/sysdeps/sparc/sparc32/tls.h.jj	2002-12-20 22:26:17.000000000 +0100
+++ libc/linuxthreads/sysdeps/sparc/sparc32/tls.h	2002-12-20 22:43:17.000000000 +0100
@@ -0,0 +1,61 @@
+/* Definitions for thread-local data handling.  linuxthreads/sparc32 version.
+   Copyright (C) 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; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _TLS_H
+#define _TLS_H
+
+#ifndef __ASSEMBLER__
+
+# include <pt-machine.h>
+# include <stddef.h>
+
+/* Type for the dtv.  */
+typedef union dtv
+{
+  size_t counter;
+  void *pointer;
+} dtv_t;
+
+typedef struct
+{
+  void *tcb;		/* Pointer to the TCB.  Not necessary the
+			   thread descriptor used by libpthread.  */
+  dtv_t *dtv;
+  void *self;		/* Pointer to the thread descriptor.  */
+  int multiple_threads;
+} tcbhead_t;
+
+#endif /* __ASSEMBLER__ */
+
+#undef USE_TLS
+
+#if USE_TLS
+
+#else
+
+#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 /* USE_TLS */
+
+#endif	/* tls.h */
--- libc/linuxthreads/sysdeps/sparc/sparc64/tls.h.jj	2002-12-20 22:26:17.000000000 +0100
+++ libc/linuxthreads/sysdeps/sparc/sparc64/tls.h	2002-12-20 22:43:27.000000000 +0100
@@ -0,0 +1,61 @@
+/* Definitions for thread-local data handling.  linuxthreads/sparc64 version.
+   Copyright (C) 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; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _TLS_H
+#define _TLS_H
+
+#ifndef __ASSEMBLER__
+
+# include <pt-machine.h>
+# include <stddef.h>
+
+/* Type for the dtv.  */
+typedef union dtv
+{
+  size_t counter;
+  void *pointer;
+} dtv_t;
+
+typedef struct
+{
+  void *tcb;		/* Pointer to the TCB.  Not necessary the
+			   thread descriptor used by libpthread.  */
+  dtv_t *dtv;
+  void *self;		/* Pointer to the thread descriptor.  */
+  int multiple_threads;
+} tcbhead_t;
+
+#endif /* __ASSEMBLER__ */
+
+#undef USE_TLS
+
+#if USE_TLS
+
+#else
+
+#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 /* USE_TLS */
+
+#endif	/* tls.h */
--- libc/linuxthreads/sysdeps/ia64/tls.h.jj	2002-12-20 14:01:54.000000000 +0100
+++ libc/linuxthreads/sysdeps/ia64/tls.h	2002-12-20 22:43:37.000000000 +0100
@@ -0,0 +1,64 @@
+/* Definitions for thread-local data handling.  linuxthreads/IA-64 version.
+   Copyright (C) 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; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _TLS_H
+#define _TLS_H
+
+#ifndef __ASSEMBLER__
+
+# include <pt-machine.h>
+# include <stddef.h>
+
+/* Type for the dtv.  */
+typedef union dtv
+{
+  size_t counter;
+  void *pointer;
+} dtv_t;
+
+
+/* FIXME: Only temporary.  When TLS is supported on IA-64,
+   pthread_descr struct needs to be immediately below r13 and
+   at r13 a struct { dtv_t *dtv; void *private; }.  */
+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;
+#endif /* __ASSEMBLER__ */
+
+#undef USE_TLS
+
+#if USE_TLS
+
+#else
+
+#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 /* USE_TLS */
+
+#endif	/* tls.h */
--- libc/linuxthreads/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h.jj	2002-12-20 14:00:36.000000000 +0100
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h	2002-12-22 22:44:42.000000000 +0100
@@ -0,0 +1,118 @@
+/* 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, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep.h>
+#include <tls.h>
+#ifndef ASSEMBLER
+# include <linuxthreads/internals.h>
+#endif
+
+#define MULTIPLE_THREADS_OFFSET	24
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)				      \
+.text;									      \
+ENTRY (name)								      \
+     adds r14 = MULTIPLE_THREADS_OFFSET, r13;;				      \
+     ld4 r14 = [r14];							      \
+     mov r15 = SYS_ify(syscall_name);;					      \
+     cmp4.ne p6, p7 = 0, r14;						      \
+(p6) br.cond.spnt .Lpseudo_cancel;;					      \
+     break __BREAK_SYSCALL;;						      \
+     cmp.eq p6,p0=-1,r10;						      \
+(p6) br.cond.spnt.few __syscall_error;					      \
+     ret;;								      \
+.Lpseudo_cancel:							      \
+     .prologue;								      \
+     .regstk args, 5, args, 0;						      \
+     .save ar.pfs, loc0;						      \
+     alloc loc0 = ar.pfs, args, 5, args, 0;				      \
+     .save rp, loc1;							      \
+     mov loc1 = rp;;							      \
+     .body;								      \
+     CENABLE;;								      \
+     mov loc2 = r8;							      \
+     COPY_ARGS_##args							      \
+     mov r15 = SYS_ify(syscall_name);					      \
+     break __BREAK_SYSCALL;;						      \
+     mov loc3 = r8;							      \
+     mov loc4 = r10;							      \
+     mov out0 = loc2;							      \
+     CDISABLE;;								      \
+     cmp.eq p6,p0=-1,loc4;						      \
+(p6) br.cond.spnt.few __syscall_error_##args;				      \
+     mov r8 = loc3;							      \
+     mov rp = loc1;							      \
+     mov ar.pfs = loc0;							      \
+.Lpseudo_end:								      \
+     ret;								      \
+     .endp name;							      \
+.section .gnu.linkonce.t.__syscall_error_##args, "ax";			      \
+     .align 32;								      \
+     .proc __syscall_error_##args;					      \
+     .global __syscall_error_##args;					      \
+     .hidden __syscall_error_##args;					      \
+__syscall_error_##args:							      \
+     .prologue;								      \
+     .regstk args, 5, args, 0;						      \
+     .save ar.pfs, loc0;						      \
+     .save rp, loc1;							      \
+     .body;								      \
+     mov loc4 = r1;;							      \
+     br.call.sptk.many b0 = __errno_location;;				      \
+     st4 [r8] = loc3;							      \
+     mov r1 = loc4;							      \
+     mov rp = loc1;							      \
+     mov r8 = -1;							      \
+     mov ar.pfs = loc0
+
+# ifdef IS_IN_libpthread
+#  define CENABLE	br.call.sptk.many b0 = __pthread_enable_asynccancel
+#  define CDISABLE	br.call.sptk.many b0 = __pthread_disable_asynccancel
+# else
+#  define CENABLE	br.call.sptk.many b0 = __libc_enable_asynccancel
+#  define CDISABLE	br.call.sptk.many b0 = __libc_disable_asynccancel
+# endif
+
+#define COPY_ARGS_0	/* Nothing */
+#define COPY_ARGS_1	COPY_ARGS_0 mov out0 = in0;
+#define COPY_ARGS_2	COPY_ARGS_1 mov out1 = in1;
+#define COPY_ARGS_3	COPY_ARGS_2 mov out2 = in2;
+#define COPY_ARGS_4	COPY_ARGS_3 mov out3 = in3;
+#define COPY_ARGS_5	COPY_ARGS_4 mov out4 = in4;
+#define COPY_ARGS_6	COPY_ARGS_5 mov out5 = in5;
+#define COPY_ARGS_7	COPY_ARGS_6 mov out6 = in6;
+
+# ifndef ASSEMBLER
+#  define SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF,				      \
+				   p_header.data.multiple_threads) == 0, 1)
+# else
+#  define SINGLE_THREAD_P \
+  adds r14 = MULTIPLE_THREADS_OFFSET, r13 ;; ld4 r14 = [r14] ;; cmp4.ne p6, p7 = 0, r14 ;;
+# endif
+
+#elif !defined ASSEMBLER
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
--- libc/linuxthreads/sysdeps/unix/sysv/linux/ia64/Makefile.jj	2002-12-20 19:07:20.000000000 +0100
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/ia64/Makefile	2002-12-20 19:07:14.000000000 +0100
@@ -0,0 +1,3 @@
+ifeq ($(subdir),linuxthreads)
+libpthread-routines += ptw-sysdep ptw-sigblock ptw-sigprocmask
+endif
--- libc/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h.jj	2002-12-20 16:53:02.000000000 +0100
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h	2002-12-22 21:18:55.000000000 +0100
@@ -0,0 +1,99 @@
+/* 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, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep.h>
+#include <tls.h>
+#ifndef ASSEMBLER
+# include <linuxthreads/internals.h>
+#endif
+
+#define MULTIPLE_THREADS_OFFSET	12
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)				      \
+	.text;								      \
+ENTRY(name)								      \
+	ld [%g6 + MULTIPLE_THREADS_OFFSET], %g1;			      \
+	cmp %g1, 0;							      \
+	bne 1f;								      \
+	 mov SYS_ify(syscall_name), %g1;				      \
+	ta 0x10;							      \
+	bcs __syscall_error_handler;					      \
+	 nop;								      \
+	.subsection 2;							      \
+1:	save %sp, -96, %sp;						      \
+	CENABLE;							      \
+	 nop;								      \
+	mov %o0, %l0;							      \
+	COPY_ARGS_##args						      \
+	mov SYS_ify(syscall_name), %g1;					      \
+	ta 0x10;							      \
+	bcs __syscall_error_handler2;					      \
+	 mov %o0, %l1;							      \
+	CDISABLE;							      \
+	 mov %l0, %o0;							      \
+	jmpl %i7 + 8, %g0;						      \
+	 restore %g0, %l1, %o0;						      \
+	.previous;							      \
+	SYSCALL_ERROR_HANDLER						      \
+	SYSCALL_ERROR_HANDLER2
+
+#define SYSCALL_ERROR_HANDLER2						      \
+SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler2)			      \
+	.global __errno_location;					      \
+        .type   __errno_location,@function;				      \
+	call   __errno_location;					      \
+	 nop;								      \
+	st	%l1, [%o0];						      \
+	jmpl	%i7 + 8, %g0;						      \
+	 restore %g0, -1, %o0;						      \
+	.previous;
+
+# ifdef IS_IN_libpthread
+#  define CENABLE	call __pthread_enable_asynccancel
+#  define CDISABLE	call __pthread_disable_asynccancel
+# else
+#  define CENABLE	call __libc_enable_asynccancel
+#  define CDISABLE	call __libc_disable_asynccancel
+# endif
+
+#define COPY_ARGS_0	/* Nothing */
+#define COPY_ARGS_1	COPY_ARGS_0 mov %i0, %o0;
+#define COPY_ARGS_2	COPY_ARGS_1 mov %i1, %o1;
+#define COPY_ARGS_3	COPY_ARGS_2 mov %i2, %o2;
+#define COPY_ARGS_4	COPY_ARGS_3 mov %i3, %o3;
+#define COPY_ARGS_5	COPY_ARGS_4 mov %i4, %o4;
+#define COPY_ARGS_6	COPY_ARGS_5 mov %i5, %o5;
+
+# ifndef ASSEMBLER
+#  define SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF,				      \
+				   p_header.data.multiple_threads) == 0, 1)
+# else
+#  define SINGLE_THREAD_P ld [%g6 + MULTIPLE_THREADS_OFFSET], %g1
+# endif
+
+#elif !defined ASSEMBLER
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
--- libc/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h.jj	2002-12-20 16:53:02.000000000 +0100
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h	2002-12-22 23:09:52.000000000 +0100
@@ -0,0 +1,98 @@
+/* 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, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep.h>
+#include <tls.h>
+#ifndef ASSEMBLER
+# include <linuxthreads/internals.h>
+#endif
+
+#define MULTIPLE_THREADS_OFFSET	24
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)				      \
+	.text;								      \
+ENTRY(name)								      \
+	ld [%g6 + MULTIPLE_THREADS_OFFSET], %g1;			      \
+	brz,pn %g1, 1f;							      \
+	 mov SYS_ify(syscall_name), %g1;				      \
+	ta 0x6d;							      \
+	bcs,pn %xcc, __syscall_error_handler;				      \
+	 nop;								      \
+	.subsection 2;							      \
+1:	save %sp, -192, %sp;						      \
+	CENABLE;							      \
+	 nop;								      \
+	mov %o0, %l0;							      \
+	COPY_ARGS_##args						      \
+	mov SYS_ify(syscall_name), %g1;					      \
+	ta 0x6d;							      \
+	bcs,pn %xcc, __syscall_error_handler2;				      \
+	 mov %o0, %l1;							      \
+	CDISABLE;							      \
+	 mov %l0, %o0;							      \
+	jmpl %i7 + 8, %g0;						      \
+	 restore %g0, %l1, %o0;						      \
+	.previous;							      \
+	SYSCALL_ERROR_HANDLER						      \
+	SYSCALL_ERROR_HANDLER2
+
+#define SYSCALL_ERROR_HANDLER2						      \
+SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler2)			      \
+	.global __errno_location;					      \
+        .type   __errno_location,@function;				      \
+	call   __errno_location;					      \
+	 nop;								      \
+	st	%l1, [%o0];						      \
+	jmpl	%i7 + 8, %g0;						      \
+	 restore %g0, -1, %o0;						      \
+	.previous;
+
+# ifdef IS_IN_libpthread
+#  define CENABLE	call __pthread_enable_asynccancel
+#  define CDISABLE	call __pthread_disable_asynccancel
+# else
+#  define CENABLE	call __libc_enable_asynccancel
+#  define CDISABLE	call __libc_disable_asynccancel
+# endif
+
+#define COPY_ARGS_0	/* Nothing */
+#define COPY_ARGS_1	COPY_ARGS_0 mov %i0, %o0;
+#define COPY_ARGS_2	COPY_ARGS_1 mov %i1, %o1;
+#define COPY_ARGS_3	COPY_ARGS_2 mov %i2, %o2;
+#define COPY_ARGS_4	COPY_ARGS_3 mov %i3, %o3;
+#define COPY_ARGS_5	COPY_ARGS_4 mov %i4, %o4;
+#define COPY_ARGS_6	COPY_ARGS_5 mov %i5, %o5;
+
+# ifndef ASSEMBLER
+#  define SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF,				      \
+				   p_header.data.multiple_threads) == 0, 1)
+# else
+#  define SINGLE_THREAD_P ld [%g6 + MULTIPLE_THREADS_OFFSET], %g1
+# endif
+
+#elif !defined ASSEMBLER
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
--- libc/linuxthreads/sysdeps/x86_64/tls.h.jj	2002-12-10 15:08:39.000000000 +0100
+++ libc/linuxthreads/sysdeps/x86_64/tls.h	2002-12-20 16:00:54.000000000 +0100
@@ -109,6 +109,11 @@ typedef struct
     _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;				      \
--- libc/linuxthreads/Makefile.jj	2002-12-20 13:35:29.000000000 +0100
+++ libc/linuxthreads/Makefile	2002-12-20 22:02:23.000000000 +0100
@@ -72,8 +72,12 @@ endif
 librt-tests = ex10 ex11
 tests = ex1 ex2 ex3 ex4 ex5 ex6 ex7 ex8 ex9 $(librt-tests) ex12 ex13 joinrace \
 	tststack $(tests-nodelete-$(have-z-nodelete)) ecmutex ex14 ex15 ex16 \
-	ex17 ex18 tst-cancel tst-context bug-sleep
+	ex17 ex18 tst-cancel tst-context bug-sleep \
+	tst-cancel1 tst-cancel2 tst-cancel3 tst-cancel4 tst-cancel5 \
+	tst-cancel6
 test-srcs = tst-signal
+# These tests are linked with libc before libpthread
+tests-reverse += tst-cancel5
 
 ifeq ($(build-static),yes)
 tests += tststatic tst-static-locale
@@ -147,8 +151,12 @@ $(objpfx)libpthread.so: $(libc-link.so) 
 # Make sure we link with the thread library.
 ifeq ($(build-shared),yes)
 $(addprefix $(objpfx), \
-  $(filter-out $(tests-static) unload, \
+  $(filter-out $(tests-static) $(tests-reverse) unload, \
     $(tests) $(test-srcs))): $(objpfx)libpthread.so
+# $(objpfx)../libc.so is used instead of $(common-objpfx)libc.so,
+# since otherwise libpthread.so comes before libc.so when linking.
+$(addprefix $(objpfx), $(tests-reverse)): \
+  $(objpfx)../libc.so $(objpfx)libpthread.so
 $(addprefix $(objpfx),$(librt-tests)): $(common-objpfx)rt/librt.so
 $(objpfx)unload: $(common-objpfx)dlfcn/libdl.so
 $(objpfx)unload.out: $(objpfx)libpthread.so
--- libc/linuxthreads/tst-cancel1.c.jj	2002-12-20 22:03:13.000000000 +0100
+++ libc/linuxthreads/tst-cancel1.c	2002-11-26 23:49:41.000000000 +0100
@@ -0,0 +1,150 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+static pthread_mutex_t m1 = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t m2 = PTHREAD_MUTEX_INITIALIZER;
+
+static int cntr;
+
+
+static void
+cleanup (void *arg)
+{
+  if (arg != (void *) 42l)
+    cntr = 42;
+  else
+    cntr = 1;
+}
+
+
+static void *
+tf (void *arg)
+{
+  int err;
+
+  pthread_cleanup_push (cleanup, (void *) 42l);
+
+  err = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+  if (err != 0)
+    {
+      printf ("setcanceltype failed: %s\n", strerror (err));
+      exit (1);
+    }
+
+  err = pthread_mutex_unlock (&m2);
+  if (err != 0)
+    {
+      printf ("child: mutex_unlock failed: %s\n", strerror (err));
+      exit (1);
+    }
+
+  err = pthread_mutex_lock (&m1);
+  if (err != 0)
+    {
+      printf ("child: 1st mutex_lock failed: %s\n", strerror (err));
+      exit (1);
+    }
+
+  /* We should never come here.  */
+
+  pthread_cleanup_pop (0);
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  int err;
+  pthread_t th;
+  int result = 0;
+  void *retval;
+
+  /* Get the mutexes.  */
+  err = pthread_mutex_lock (&m1);
+  if (err != 0)
+    {
+      printf ("parent: 1st mutex_lock failed: %s\n", strerror (err));
+      return 1;
+    }
+  err = pthread_mutex_lock (&m2);
+  if (err != 0)
+    {
+      printf ("parent: 2nd mutex_lock failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  err = pthread_create (&th, NULL, tf, NULL);
+  if (err != 0)
+    {
+      printf ("create failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  err = pthread_mutex_lock (&m2);
+  if (err != 0)
+    {
+      printf ("parent: 3rd mutex_lock failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  err = pthread_cancel (th);
+  if (err != 0)
+    {
+      printf ("cancel failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  err = pthread_join (th, &retval);
+  if (err != 0)
+    {
+      printf ("join failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  if (retval != PTHREAD_CANCELED)
+    {
+      printf ("wrong return value: %p\n", retval);
+      result = 1;
+    }
+
+  if (cntr == 42)
+    {
+      puts ("cleanup handler called with wrong argument");
+      result = 1;
+    }
+  else if (cntr != 1)
+    {
+      puts ("cleanup handling not called");
+      result = 1;
+    }
+
+  return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- libc/linuxthreads/tst-cancel2.c.jj	2002-12-20 22:03:13.000000000 +0100
+++ libc/linuxthreads/tst-cancel2.c	2002-11-26 23:49:53.000000000 +0100
@@ -0,0 +1,100 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+static int fd[2];
+
+
+static void *
+tf (void *arg)
+{
+  /* The buffer size must be larger than the pipe size so that the
+     write blocks.  */
+  char buf[100000];
+
+  if (write (fd[1], buf, sizeof (buf)) == sizeof (buf))
+    {
+      puts ("write succeeded");
+      return (void *) 1l;
+    }
+
+  return (void *) 42l;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+  void *r;
+  struct sigaction sa;
+
+  sa.sa_handler = SIG_IGN;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = 0;
+
+  if (sigaction (SIGPIPE, &sa, NULL) != 0)
+    {
+      puts ("sigaction failed");
+      return 1;
+    }
+
+  if (pipe (fd) != 0)
+    {
+      puts ("pipe failed");
+      return 1;
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cancel failed");
+      return 1;
+    }
+
+  /* This will cause the write in the child to return.  */
+  close (fd[0]);
+
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+
+  if (r != PTHREAD_CANCELED)
+    {
+      printf ("result is wrong: expected %p, got %p\n", PTHREAD_CANCELED, r);
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- libc/linuxthreads/tst-cancel3.c.jj	2002-12-20 22:03:13.000000000 +0100
+++ libc/linuxthreads/tst-cancel3.c	2002-11-26 23:49:53.000000000 +0100
@@ -0,0 +1,98 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+static int fd[2];
+
+
+static void *
+tf (void *arg)
+{
+  char buf[100];
+
+  if (read (fd[0], buf, sizeof (buf)) == sizeof (buf))
+    {
+      puts ("read succeeded");
+      return (void *) 1l;
+    }
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+  void *r;
+  struct sigaction sa;
+
+  sa.sa_handler = SIG_IGN;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = 0;
+
+  if (sigaction (SIGPIPE, &sa, NULL) != 0)
+    {
+      puts ("sigaction failed");
+      return 1;
+    }
+
+  if (pipe (fd) != 0)
+    {
+      puts ("pipe failed");
+      return 1;
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cancel failed");
+      return 1;
+    }
+
+  /* This will cause the read in the child to return.  */
+  close (fd[0]);
+
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+
+  if (r != PTHREAD_CANCELED)
+    {
+      puts ("result is wrong");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- libc/linuxthreads/tst-cancel4.c.jj	2002-12-20 22:03:13.000000000 +0100
+++ libc/linuxthreads/tst-cancel4.c	2002-12-20 21:58:50.000000000 +0100
@@ -0,0 +1,461 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* NOTE: this tests functionality beyond POSIX.  POSIX does not allow
+   exit to be called more than once.  */
+
+#include <errno.h>
+#include <limits.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/poll.h>
+#include <sys/select.h>
+#include <sys/uio.h>
+#include <sys/wait.h>
+
+/* The following interfaces are defined to be cancellation points but
+   tests are not yet implemented:
+
+     accept()              aio_suspend()      clock_nanosleep()
+     close()               connect()          creat()
+     fcntl()               fsync()            getmsg()
+     getpmsg()             lockf()            mq_receive()
+     mq_send()             mq_timedreceive()  mq_timedsend()
+     msgrcv()              msgsnd()           msync()
+                           open()             pause()
+                           pread()            pthread_cond_timedwait()
+     pthread_cond_wait()   pthread_join()     pthread_testcancel()
+     putmsg()              putpmsg()          pwrite()
+                                              recv()
+     recvfrom()            recvmsg()
+     sem_timedwait()       sem_wait()         send()
+     sendmsg()             sendto()           sigpause()
+     sigsuspend()          sigtimedwait()     sigwait()
+     sigwaitinfo()                            system()
+     tcdrain()
+
+   Since STREAMS are not supported in the standard Linux kernel there
+   is no need to test the STREAMS related functions.
+*/
+
+/* Pipe descriptors.  */
+static int fds[2];
+
+/* Often used barrier for two threads.  */
+static pthread_barrier_t b2;
+
+
+static void *
+tf_read  (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  char buf[100];
+  ssize_t s = read (fds[0], buf, sizeof (buf));
+
+  printf ("%s: read returns with %zd\n", __FUNCTION__, s);
+
+  exit (1);
+}
+
+
+static void *
+tf_readv  (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  char buf[100];
+  struct iovec iov[1] = { [0] = { .iov_base = buf, .iov_len = sizeof (buf) } };
+  ssize_t s = readv (fds[0], iov, 1);
+
+  printf ("%s: readv returns with %zd\n", __FUNCTION__, s);
+
+  exit (1);
+}
+
+
+static void *
+tf_write  (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  char buf[100000];
+  memset (buf, '\0', sizeof (buf));
+  ssize_t s = write (fds[1], buf, sizeof (buf));
+
+  printf ("%s: write returns with %zd\n", __FUNCTION__, s);
+
+  exit (1);
+}
+
+
+static void *
+tf_writev  (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  char buf[100000];
+  memset (buf, '\0', sizeof (buf));
+  struct iovec iov[1] = { [0] = { .iov_base = buf, .iov_len = sizeof (buf) } };
+  ssize_t s = writev (fds[1], iov, 1);
+
+  printf ("%s: writev returns with %zd\n", __FUNCTION__, s);
+
+  exit (1);
+}
+
+
+static void *
+tf_sleep (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  sleep (10000000);
+
+  printf ("%s: sleep returns\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_usleep (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  usleep ((useconds_t) ULONG_MAX);
+
+  printf ("%s: usleep returns\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_nanosleep (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  struct timespec ts = { .tv_sec = 10000000, .tv_nsec = 0 };
+  while (nanosleep (&ts, &ts) != 0)
+    continue;
+
+  printf ("%s: nanosleep returns\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_select (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  fd_set rfs;
+  FD_ZERO (&rfs);
+  FD_SET (fds[0], &rfs);
+
+  int s = select (fds[0] + 1, &rfs, NULL, NULL, NULL);
+
+  printf ("%s: select returns with %d (%s)\n", __FUNCTION__, s,
+	  strerror (errno));
+
+  exit (1);
+}
+
+
+static void *
+tf_pselect (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  fd_set rfs;
+  FD_ZERO (&rfs);
+  FD_SET (fds[0], &rfs);
+
+  int s = pselect (fds[0] + 1, &rfs, NULL, NULL, NULL, NULL);
+
+  printf ("%s: pselect returns with %d (%s)\n", __FUNCTION__, s,
+	  strerror (errno));
+
+  exit (1);
+}
+
+
+static void *
+tf_poll (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  struct pollfd rfs[1] = { [0] = { .fd = fds[0], .events = POLLIN } };
+
+  int s = poll (rfs, 1, -1);
+
+  printf ("%s: poll returns with %d (%s)\n", __FUNCTION__, s,
+	  strerror (errno));
+
+  exit (1);
+}
+
+
+static void *
+tf_wait (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  pid_t pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      exit (1);
+    }
+
+  if (pid == 0)
+    {
+      /* Make the program disappear after a while.  */
+      sleep (10);
+      exit (0);
+    }
+
+  int s = wait (NULL);
+
+  printf ("%s: wait returns with %d (%s)\n", __FUNCTION__, s,
+	  strerror (errno));
+
+  exit (1);
+}
+
+
+static void *
+tf_waitpid (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  pid_t pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      exit (1);
+    }
+
+  if (pid == 0)
+    {
+      /* Make the program disappear after a while.  */
+      sleep (10);
+      exit (0);
+    }
+
+  int s = waitpid (-1, NULL, 0);
+
+  printf ("%s: waitpid returns with %d (%s)\n", __FUNCTION__, s,
+	  strerror (errno));
+
+  exit (1);
+}
+
+
+static void *
+tf_waitid (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  pid_t pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      exit (1);
+    }
+
+  if (pid == 0)
+    {
+      /* Make the program disappear after a while.  */
+      sleep (10);
+      exit (0);
+    }
+
+  siginfo_t si;
+  int s = waitid (P_PID, pid, &si, 0);
+
+  printf ("%s: waitid returns with %d (%s)\n", __FUNCTION__, s,
+	  strerror (errno));
+
+  exit (1);
+}
+
+
+static struct
+{
+  void *(*tf) (void *);
+  int nb;
+} tests[] =
+{
+  { tf_read, 2 },
+  { tf_readv, 2 },
+  { tf_select, 2 },
+  { tf_pselect, 2 },
+  { tf_poll, 2 },
+  { tf_write, 2 },
+  { tf_writev, 2},
+  { tf_sleep, 2 },
+  { tf_usleep, 2 },
+  { tf_nanosleep, 2 },
+  { tf_wait, 2 },
+  { tf_waitid, 2 },
+  { tf_waitpid, 2 },
+};
+#define ntest_tf (sizeof (tests) / sizeof (tests[0]))
+
+
+static int
+do_test (void)
+{
+  if (pipe (fds) != 0)
+    {
+      puts ("pipe failed");
+      exit (1);
+    }
+
+  int cnt;
+  for (cnt = 0; cnt < ntest_tf; ++cnt)
+    {
+      if (pthread_barrier_init (&b2, NULL, tests[cnt].nb) != 0)
+	{
+	  puts ("b2 init failed");
+	  exit (1);
+	}
+
+      /* read(2) test.  */
+      pthread_t th;
+      if (pthread_create (&th, NULL, tests[cnt].tf, NULL) != 0)
+	{
+	  printf ("create for round %d test failed\n", cnt);
+	  exit (1);
+	}
+
+      int r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+
+      struct timespec  ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+      while (nanosleep (&ts, &ts) != 0)
+	continue;
+
+      if (pthread_cancel (th) != 0)
+	{
+	  printf ("cancel in round %d failed\n", cnt);
+	  exit (1);
+	}
+
+      void *status;
+      if (pthread_join (th, &status) != 0)
+	{
+	  printf ("join in round %d failed\n", cnt);
+	  exit (1);
+	}
+      if (status != PTHREAD_CANCELED)
+	{
+	  printf ("thread in round %d not canceled\n", cnt);
+	  exit (1);
+	}
+      printf ("test %d successful\n", cnt);
+
+      if (pthread_barrier_destroy (&b2) != 0)
+	{
+	  puts ("barrier_destroy failed");
+	  exit (1);
+	}
+    }
+
+  return 0;
+}
+
+#define TIMEOUT 60
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- libc/linuxthreads/tst-cancel5.c.jj	2002-12-20 22:03:13.000000000 +0100
+++ libc/linuxthreads/tst-cancel5.c	2002-12-14 20:28:32.000000000 +0100
@@ -0,0 +1 @@
+#include "tst-cancel4.c"
--- libc/linuxthreads/tst-cancel6.c.jj	2002-12-20 22:03:13.000000000 +0100
+++ libc/linuxthreads/tst-cancel6.c	2002-12-17 23:47:54.000000000 +0100
@@ -0,0 +1,79 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static void *
+tf (void *arg)
+{
+  char buf[100];
+  fgets (buf, sizeof (buf), arg);
+  /* This call should never return.  */
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  int fd[2];
+  if (pipe (fd) != 0)
+    {
+      puts ("pipe failed");
+      return 1;
+    }
+
+  FILE *fp = fdopen (fd[0], "r");
+  if (fp == NULL)
+    {
+      puts ("fdopen failed");
+      return 1;
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, fp) != 0)
+    {
+      puts ("pthread_create failed");
+      return 1;
+    }
+
+  sleep (1);
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("pthread_cancel failed");
+      return 1;
+    }
+
+  void *r;
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("pthread_join failed");
+      return 1;
+    }
+
+  return r != PTHREAD_CANCELED;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- libc/sysdeps/generic/libc-tls.c.jj	2002-12-10 15:08:54.000000000 +0100
+++ libc/sysdeps/generic/libc-tls.c	2002-12-20 20:37:00.000000000 +0100
@@ -135,8 +135,13 @@ __libc_setup_tls (size_t tcbsize, size_t
 	}
 
   if (memsz == 0 && tcbsize <= TLS_INIT_TCB_SIZE)
-    /* We do not need a TLS block and no thread descriptor.  */
-    return;
+    {
+      /* We do not need a TLS block and no thread descriptor.  */
+#ifdef NONTLS_INIT_TP
+      NONTLS_INIT_TP;
+#endif
+      return;
+    }
 
 
   /* We have to set up the TCB block which also (possibly) contains
@@ -249,4 +254,16 @@ __pthread_initialize_minimal (void)
 {
   __libc_setup_tls (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN);
 }
+
+#elif defined NONTLS_INIT_TP
+
+/* This is the minimal initialization function used when libpthread is
+   not used.  */
+void
+__attribute__ ((weak))
+__pthread_initialize_minimal (void)
+{
+  NONTLS_INIT_TP;
+}
+
 #endif
--- libc/sysdeps/generic/libc-start.c.jj	2002-12-10 15:08:54.000000000 +0100
+++ libc/sysdeps/generic/libc-start.c	2002-12-20 22:00:08.000000000 +0100
@@ -32,7 +32,7 @@ extern void *__libc_stack_end;
 #ifndef SHARED
 # include <dl-osinfo.h>
 extern void __pthread_initialize_minimal (void)
-# if !(USE_TLS - 0)
+# if !(USE_TLS - 0) && !defined NONTLS_INIT_TP
      __attribute__ ((weak))
 # endif
      ;
@@ -97,7 +97,7 @@ BP_SYM (__libc_start_main) (int (*main) 
      we need to setup errno.  If there is no thread library and we
      handle TLS the function is defined in the libc to initialized the
      TLS handling.  */
-# if !(USE_TLS - 0)
+# if !(USE_TLS - 0) && !defined NONTLS_INIT_TP
   if (__pthread_initialize_minimal)
 # endif
     __pthread_initialize_minimal ();
--- libc/sysdeps/unix/common/pause.c.jj	2001-08-23 18:50:34.000000000 +0200
+++ libc/sysdeps/unix/common/pause.c	2002-12-20 21:33:08.000000000 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1996 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1996, 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
@@ -18,7 +18,7 @@
 
 #include <signal.h>
 #include <unistd.h>
-
+#include <sysdep-cancel.h>
 
 /* Suspend the process until a signal arrives.
    This always returns -1 and sets errno to EINTR.  */
@@ -26,6 +26,12 @@
 int
 __libc_pause (void)
 {
-  return __sigpause (__sigblock (0), 0);
+  if (SINGLE_THREAD_P)
+    return __sigpause (__sigblock (0), 0);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+  int result = __sigpause (__sigblock (0), 0);
+  LIBC_CANCEL_RESET (oldtype);
+  return result;
 }
 weak_alias (__libc_pause, pause)
--- libc/sysdeps/unix/sysv/linux/ia64/sysdep.h.jj	2002-12-10 15:09:30.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/ia64/sysdep.h	2002-12-20 14:00:36.000000000 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Jes Sorensen, <Jes.Sorensen@cern.ch>, April 1999.
    Based on code originally written by David Mosberger-Tang
@@ -83,7 +83,7 @@
 #define	PSEUDO(name, syscall_name, args)	\
   ENTRY(name)					\
     DO_CALL (SYS_ify(syscall_name));		\
-	cmp.eq p6,p0=-1,r10;;			\
+	cmp.eq p6,p0=-1,r10;			\
 (p6)	br.cond.spnt.few __syscall_error;
 
 #define DO_CALL(num)				\
@@ -102,11 +102,98 @@
 
 #else /* not __ASSEMBLER__ */
 
-/* Define a macro which expands into the inline wrapper code for a system
-   call.  */
-#if 0
+/* On IA-64 we have stacked registers for passing arguments.  The
+   "out" registers end up being the called function's "in"
+   registers.
+
+   Also, since we have plenty of registers we have two return values
+   from a syscall.  r10 is set to -1 on error, whilst r8 contains the
+   (non-negative) errno on error or the return value on success.
+ */
 #undef INLINE_SYSCALL
-#define INLINE_SYSCALL(name, nr, args...)	__##name (args)
-#endif
+#define INLINE_SYSCALL(name, nr, args...)			\
+  ({								\
+    register long _r8 asm ("r8");				\
+    register long _r10 asm ("r10");				\
+    register long _r15 asm ("r15") = __NR_##name;		\
+    long _retval;						\
+    LOAD_ARGS_##nr (args);					\
+    __asm __volatile ("break %3;;\n\t"				\
+                      : "=r" (_r8), "=r" (_r10), "=r" (_r15)	\
+                      : "i" (__BREAK_SYSCALL), "2" (_r15)	\
+			ASM_ARGS_##nr				\
+                      : "memory" ASM_CLOBBERS_##nr);		\
+    _retval = _r8;						\
+    if (_r10 == -1)						\
+      {								\
+        __set_errno (_retval);					\
+        _retval = -1;						\
+      }								\
+    _retval; })
+
+#undef INTERNAL_SYSCALL
+#define INTERNAL_SYSCALL(name, nr, args...)			\
+  ({								\
+    register long _r8 asm ("r8");				\
+    register long _r10 asm ("r10");				\
+    register long _r15 asm ("r15") = __NR_##name;		\
+    long _retval;						\
+    LOAD_ARGS_##nr (args);					\
+    __asm __volatile ("break %3;;\n\t"				\
+                      : "=r" (_r8), "=r" (_r10), "=r" (_r15)	\
+                      : "i" (__BREAK_SYSCALL), "2" (_r15)	\
+			ASM_ARGS_##nr				\
+                      : "memory" ASM_CLOBBERS_##nr);		\
+    _retval = _r8;						\
+    if (_r10 == -1)						\
+      _retval = -_retval;					\
+    _retval; })
+
+#undef INTERNAL_SYSCALL_ERROR_P
+#define INTERNAL_SYSCALL_ERROR_P(val)	((unsigned long) (val) >= -4095UL)
+
+#undef INTERNAL_SYSCALL_ERRNO
+#define INTERNAL_SYSCALL_ERRNO(val)	(-(val))
+
+#define LOAD_ARGS_0()   do { } while (0)
+#define LOAD_ARGS_1(out0)				\
+  register long _out0 asm ("out0") = (long) (out0);	\
+  LOAD_ARGS_0 ()
+#define LOAD_ARGS_2(out0, out1)				\
+  register long _out1 asm ("out1") = (long) (out1);	\
+  LOAD_ARGS_1 (out0)
+#define LOAD_ARGS_3(out0, out1, out2)			\
+  register long _out2 asm ("out2") = (long) (out2);	\
+  LOAD_ARGS_2 (out0, out1)
+#define LOAD_ARGS_4(out0, out1, out2, out3)		\
+  register long _out3 asm ("out3") = (long) (out3);	\
+  LOAD_ARGS_3 (out0, out1, out2)
+#define LOAD_ARGS_5(out0, out1, out2, out3, out4)	\
+  register long _out4 asm ("out4") = (long) (out4);	\
+  LOAD_ARGS_4 (out0, out1, out2, out3)
+
+#define ASM_ARGS_0
+#define ASM_ARGS_1      ASM_ARGS_0, "r" (_out0)
+#define ASM_ARGS_2      ASM_ARGS_1, "r" (_out1)
+#define ASM_ARGS_3      ASM_ARGS_2, "r" (_out2)
+#define ASM_ARGS_4      ASM_ARGS_3, "r" (_out3)
+#define ASM_ARGS_5      ASM_ARGS_4, "r" (_out4)
+
+#define ASM_CLOBBERS_0	ASM_CLOBBERS_1, "out0"
+#define ASM_CLOBBERS_1	ASM_CLOBBERS_2, "out1"
+#define ASM_CLOBBERS_2	ASM_CLOBBERS_3, "out2"
+#define ASM_CLOBBERS_3	ASM_CLOBBERS_4, "out3"
+#define ASM_CLOBBERS_4	ASM_CLOBBERS_5, "out4"
+#define ASM_CLOBBERS_5	, "out5", "out6", "out7",			\
+  /* Non-stacked integer registers, minus r8, r10, r15.  */		\
+  "r2", "r3", "r9", "r11", "r12", "r13", "r14", "r16", "r17", "r18",	\
+  "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27",	\
+  "r28", "r29", "r30", "r31",						\
+  /* Predicate registers.  */						\
+  "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15",	\
+  /* Non-rotating fp registers.  */					\
+  "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",	\
+  /* Branch registers.  */						\
+  "b6", "b7"
 
 #endif /* not __ASSEMBLER__ */
--- libc/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep.h.jj	2002-10-25 12:34:51.000000000 +0200
+++ libc/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep.h	2002-12-22 19:29:19.000000000 +0100
@@ -31,11 +31,7 @@
 
 #ifdef __ASSEMBLER__
 
-#ifdef DONT_LOAD_G1
-# define LOADSYSCALL(x)
-#else
-# define LOADSYSCALL(x) mov __NR_##x, %g1
-#endif
+#define LOADSYSCALL(x) mov __NR_##x, %g1
 
 /* Linux/SPARC uses a different trap number */
 #undef PSEUDO
@@ -54,6 +50,21 @@
 
 #define LOC(name)  .L##name
 
+#ifdef LINKER_HANDLES_R_SPARC_WDISP22
+/* Unfortunately, we cannot do this yet.  Linker doesn't seem to
+   handle R_SPARC_WDISP22 against non-STB_LOCAL symbols properly .  */
+# define SYSCALL_ERROR_HANDLER_ENTRY(handler)				\
+	.section .gnu.linkonce.t.handler,"ax",@progbits;		\
+	.globl handler;							\
+	.hidden handler;						\
+	.type handler,@function;					\
+handler:
+#else
+# define SYSCALL_ERROR_HANDLER_ENTRY(handler)				\
+	.subsection 3;							\
+handler:
+#endif
+
 #if RTLD_PRIVATE_ERRNO
 # define SYSCALL_ERROR_HANDLER						\
 	.section .gnu.linkonce.t.__sparc.get_pic.l7,"ax",@progbits;	\
@@ -64,6 +75,7 @@ __sparc.get_pic.l7:							\
 	retl;								\
 	 add	%o7, %l7, %l7;						\
 	.previous;							\
+SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler)			\
 	save	%sp,-96,%sp;						\
 	sethi	%hi(_GLOBAL_OFFSET_TABLE_-4), %l7;			\
 	call	__sparc.get_pic.l7;					\
@@ -71,17 +83,20 @@ __sparc.get_pic.l7:							\
 	ld	[%l7 + errno], %l0;					\
 	st	%i0, [%l0];						\
 	jmpl	%i7+8, %g0;						\
-	 restore %g0, -1, %o0;
+	 restore %g0, -1, %o0;						\
+	.previous;
 #else
-# define SYSCALL_ERROR_HANDLER					\
-	.global __errno_location;				\
-        .type   __errno_location,@function;			\
-	save   %sp, -96, %sp;					\
-	call   __errno_location;				\
-	 nop;							\
-	st	%i0, [%o0];					\
-	jmpl	%i7+8, %g0;					\
-	 restore %g0, -1, %o0;
+# define SYSCALL_ERROR_HANDLER						\
+SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler)			\
+	.global __errno_location;					\
+        .type   __errno_location,@function;				\
+	save   %sp, -96, %sp;						\
+	call   __errno_location;					\
+	 nop;								\
+	st	%i0, [%o0];						\
+	jmpl	%i7+8, %g0;						\
+	 restore %g0, -1, %o0;						\
+	.previous;
 #endif
 
 #define PSEUDO(name, syscall_name, args)			\
@@ -89,10 +104,9 @@ __sparc.get_pic.l7:							\
 	ENTRY(name);						\
 	LOADSYSCALL(syscall_name);				\
 	ta 0x10;						\
-	bcc,a 9000f;						\
-	nop;							\
-	SYSCALL_ERROR_HANDLER;					\
-9000:;
+	bcs __syscall_error_handler;				\
+	 nop;							\
+	SYSCALL_ERROR_HANDLER
 
 #else  /* __ASSEMBLER__ */
 
--- libc/sysdeps/unix/sysv/linux/sparc/sparc32/pipe.S.jj	2002-08-03 11:09:58.000000000 +0200
+++ libc/sysdeps/unix/sysv/linux/sparc/sparc32/pipe.S	2002-12-20 19:56:05.000000000 +0100
@@ -18,19 +18,19 @@
    02111-1307 USA.  */
 
 #include <sysdep.h>
+
 	.globl __libc_pipe
 ENTRY (__libc_pipe)
         mov %o0, %o2            /* Save PIPEDES. */
 	mov SYS_ify(pipe),%g1
 	ta 0x10
-	bcc,a 2f
-	nop
-	SYSCALL_ERROR_HANDLER
-2:
+	bcs __syscall_error_handler
+	 nop
 	st %o0, [%o2]           /* PIPEDES[0] = %o0; */
         st %o1, [%o2 + 4]       /* PIPEDES[1] = %o1; */
 	retl
-	clr %o0
+	 clr %o0
+	SYSCALL_ERROR_HANDLER
 
 PSEUDO_END (__libc_pipe)
 weak_alias (__libc_pipe, __pipe)
--- libc/sysdeps/unix/sysv/linux/sparc/sparc32/socket.S.jj	2001-08-23 18:51:33.000000000 +0200
+++ libc/sysdeps/unix/sysv/linux/sparc/sparc32/socket.S	2002-12-20 19:59:04.000000000 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1998, 2002 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Miguel de Icaza <miguel@gnu.ai.mit.edu>, 1997.
 
@@ -67,13 +67,12 @@ ENTRY (__socket)
 	add %sp, 68, %o1		/* arg 2: parameter block */
 	LOADSYSCALL(socketcall)
 	t 0x10
-
-        bcs,a 1f
+        bcs __syscall_error_handler
 	 nop
 	retl
 	 nop
 
-1:	SYSCALL_ERROR_HANDLER
+	SYSCALL_ERROR_HANDLER
 
 END (__socket)
 
--- libc/sysdeps/unix/sysv/linux/sparc/sparc32/syscall.S.jj	2001-08-23 18:51:33.000000000 +0200
+++ libc/sysdeps/unix/sysv/linux/sparc/sparc32/syscall.S	2002-12-20 19:58:53.000000000 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1992, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1992, 1997, 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
@@ -19,23 +19,17 @@
 #include <sysdep.h>
 	.text
 ENTRY (syscall)
-	or	%o0,%g0,%g1
-	or	%o1,%g0,%o0
-	or	%o2,%g0,%o1
-	or	%o3,%g0,%o2
-	or	%o4,%g0,%o3
-	or	%o5,%g0,%o4
+	mov	%o0, %g1
+	mov	%o1, %o0
+	mov	%o2, %o1
+	mov	%o3, %o2
+	mov	%o4, %o3
+	mov	%o5, %o4
 	ta	0x10
-	bcc	1f
-	nop
-	save %sp, -96, %sp
-	call __errno_location
-	nop
-	st %i0,[%o0]
-	restore
+	bcs	__syscall_error_handler
+	 nop
 	retl
-	mov -1, %o0
-1:
-	ret
+	 nop
+	SYSCALL_ERROR_HANDLER
 
 PSEUDO_END (syscall)
--- libc/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep.h.jj	2002-12-10 15:13:34.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep.h	2002-12-22 23:08:08.000000000 +0100
@@ -31,11 +31,7 @@
 
 #ifdef __ASSEMBLER__
 
-#ifdef DONT_LOAD_G1
-# define LOADSYSCALL(x)
-#else
-# define LOADSYSCALL(x) mov __NR_##x, %g1
-#endif
+#define LOADSYSCALL(x) mov __NR_##x, %g1
 
 /* Linux/SPARC uses a different trap number */
 #undef PSEUDO
@@ -47,6 +43,21 @@
 	C_LABEL(name);							\
 	.type name,@function;
 
+#ifdef LINKER_HANDLES_R_SPARC_WDISP22
+/* Unfortunately, we cannot do this yet.  Linker doesn't seem to
+   handle R_SPARC_WDISP22 against non-STB_LOCAL symbols properly .  */
+# define SYSCALL_ERROR_HANDLER_ENTRY(handler)				\
+	.section .gnu.linkonce.t.handler,"ax",@progbits;		\
+	.globl handler;							\
+	.hidden handler;						\
+	.type handler,@function;					\
+handler:
+#else
+# define SYSCALL_ERROR_HANDLER_ENTRY(handler)				\
+	.subsection 3;							\
+handler:
+#endif
+
 #if RTLD_PRIVATE_ERRNO
 # define SYSCALL_ERROR_HANDLER						\
 	.section .gnu.linkonce.t.__sparc64.get_pic.l7,"ax",@progbits;	\
@@ -57,6 +68,7 @@ __sparc64.get_pic.l7:							\
 	retl;								\
 	 add	%o7, %l7, %l7;						\
 	.previous;							\
+SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler)			\
 	save	%sp, -192, %sp;						\
 	sethi	%hi(_GLOBAL_OFFSET_TABLE_-4), %l7;			\
 	call	__sparc64.get_pic.l7;					\
@@ -64,17 +76,20 @@ __sparc64.get_pic.l7:							\
 	ldx	[%l7 + errno], %l0;					\
 	st	%i0, [%l0];						\
 	jmpl	%i7+8, %g0;						\
-	 restore %g0, -1, %o0;
+	 restore %g0, -1, %o0;						\
+	.previous;
 #else
-# define SYSCALL_ERROR_HANDLER					\
-	.global __errno_location;				\
-	.type   __errno_location,@function;			\
-	save	%sp, -192, %sp;					\
-	call	__errno_location;				\
-	 nop;							\
-	st	%i0, [%o0];					\
-	jmpl	%i7+8, %g0;					\
-	 restore %g0, -1, %o0;
+# define SYSCALL_ERROR_HANDLER						\
+SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler)			\
+	.global __errno_location;					\
+	.type   __errno_location,@function;				\
+	save	%sp, -192, %sp;						\
+	call	__errno_location;					\
+	 nop;								\
+	st	%i0, [%o0];						\
+	jmpl	%i7+8, %g0;						\
+	 restore %g0, -1, %o0;						\
+	.previous;
 #endif
 
 #define PSEUDO(name, syscall_name, args)				\
@@ -82,10 +97,9 @@ __sparc64.get_pic.l7:							\
 	ENTRY(name);							\
 	LOADSYSCALL(syscall_name);					\
 	ta	0x6d;							\
-	bcc,pt	%xcc, 1f;						\
+	bcs,pn	%xcc, __syscall_error_handler;				\
 	 nop;								\
-	SYSCALL_ERROR_HANDLER;						\
-1:
+	SYSCALL_ERROR_HANDLER
 
 #undef PSEUDO_END
 #define PSEUDO_END(name)						\
--- libc/sysdeps/unix/sysv/linux/sparc/sparc64/pipe.S.jj	2002-08-03 11:09:59.000000000 +0200
+++ libc/sysdeps/unix/sysv/linux/sparc/sparc64/pipe.S	2002-12-20 21:10:52.000000000 +0100
@@ -23,14 +23,13 @@ ENTRY (__libc_pipe)
 	mov	%o0, %o2		/* Save PIPEDES. */
 	LOADSYSCALL(pipe)
 	ta	0x6d
-	bcc,pt	%xcc, 2f
+	bcs,pn	%xcc, __syscall_error_handler
 	 nop
-	SYSCALL_ERROR_HANDLER
-
-2:	st	%o0, [%o2]		/* PIPEDES[0] = %o0; */
+	st	%o0, [%o2]		/* PIPEDES[0] = %o0; */
 	st	%o1, [%o2 + 4]		/* PIPEDES[1] = %o1; */
 	retl
 	 clr	%o0
+	SYSCALL_ERROR_HANDLER
 PSEUDO_END (__libc_pipe)
 
 weak_alias (__libc_pipe, __pipe)
--- libc/sysdeps/unix/sysv/linux/sparc/sparc64/socket.S.jj	2001-08-23 18:51:33.000000000 +0200
+++ libc/sysdeps/unix/sysv/linux/sparc/sparc64/socket.S	2002-12-20 21:11:38.000000000 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1998, 2002 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Miguel de Icaza <miguel@gnu.ai.mit.edu>, 1997.
 
@@ -68,12 +68,12 @@ ENTRY (__socket)
 	LOADSYSCALL(socketcall)
 	ta	0x6d
 
-        bcs,pn	%xcc, 1f
+	bcs,pn	%xcc, __syscall_error_handler
 	 nop
 	retl
 	 nop
 
-1:	SYSCALL_ERROR_HANDLER
+	SYSCALL_ERROR_HANDLER
 
 END (__socket)
 
--- libc/sysdeps/unix/sysv/linux/sparc/sparc64/syscall.S.jj	2001-08-23 18:51:33.000000000 +0200
+++ libc/sysdeps/unix/sysv/linux/sparc/sparc64/syscall.S	2002-12-20 21:16:58.000000000 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997, 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1999, 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
@@ -30,11 +30,11 @@ ENTRY (syscall)
 
 	ta	0x6d
 
-	bcc,pt %xcc,1f
+	bcs,pn %xcc,__syscall_error_handler
 	 nop
-	SYSCALL_ERROR_HANDLER
-
-1:	retl
+	retl
 	 nop
 
+	SYSCALL_ERROR_HANDLER
+
 PSEUDO_END (syscall)
--- libc/nptl/Makefile.jj	2002-12-20 12:17:13.000000000 +0100
+++ libc/nptl/Makefile	2002-12-20 21:58:19.000000000 +0100
@@ -214,8 +214,10 @@ $(addprefix $(objpfx), \
     $(tests) $(test-srcs))): $(objpfx)libpthread.so \
 			     $(objpfx)libpthread_nonshared.a
 $(objpfx)tst-unload: $(common-objpfx)dlfcn/libdl.so
+# $(objpfx)../libc.so is used instead of $(common-objpfx)libc.so,
+# since otherwise libpthread.so comes before libc.so when linking.
 $(addprefix $(objpfx), $(tests-reverse)): \
-  $(common-objpfx)libc.so $(objpfx)libpthread.so \
+  $(objpfx)../libc.so $(objpfx)libpthread.so \
   $(objpfx)libpthread_nonshared.a
 $(addprefix $(objpfx),$(tests-static)): $(objpfx)libpthread.a
 else
--- libc/nptl/tst-cancel4.c.jj	2002-11-26 23:50:02.000000000 +0100
+++ libc/nptl/tst-cancel4.c	2002-12-20 21:58:50.000000000 +0100
@@ -113,7 +113,7 @@ tf_write  (void *arg)
       exit (1);
     }
 
-  char buf[10000];
+  char buf[100000];
   memset (buf, '\0', sizeof (buf));
   ssize_t s = write (fds[1], buf, sizeof (buf));
 
@@ -133,7 +133,7 @@ tf_writev  (void *arg)
       exit (1);
     }
 
-  char buf[10000];
+  char buf[100000];
   memset (buf, '\0', sizeof (buf));
   struct iovec iov[1] = { [0] = { .iov_base = buf, .iov_len = sizeof (buf) } };
   ssize_t s = writev (fds[1], iov, 1);
@@ -172,7 +172,7 @@ tf_usleep (void *arg)
       exit (1);
     }
 
-  usleep (ULONG_MAX);
+  usleep ((useconds_t) ULONG_MAX);
 
   printf ("%s: usleep returns\n", __FUNCTION__);
 


	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]