about summary refs log tree commit diff
path: root/nptl/sysdeps/unix/sysv/linux/sh
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2004-03-20 06:16:26 +0000
committerUlrich Drepper <drepper@redhat.com>2004-03-20 06:16:26 +0000
commit07bd2a3fda47e7cfa83e808eb99a0da9d1184a30 (patch)
treea0e41495d990b736c8981a58677bc28175621728 /nptl/sysdeps/unix/sysv/linux/sh
parent3abb1ff7d1c7a2941df3c6234ec71b40a3879baa (diff)
downloadglibc-07bd2a3fda47e7cfa83e808eb99a0da9d1184a30.tar.gz
glibc-07bd2a3fda47e7cfa83e808eb99a0da9d1184a30.tar.xz
glibc-07bd2a3fda47e7cfa83e808eb99a0da9d1184a30.zip
Update.
2004-03-17  Kaz Kojima  <kkojima@rr.iij4u.or.jp>

	* sysdeps/unix/sysv/linux/kernel-features.h
	(__ASSUME_CLONE_THREAD_FLAGS ): Define for newer SH kernel.
	(__ASSUME_TGKILL, __ASSUME_UTIMES): Likewise.
	* sysdeps/unix/sysv/linux/sh/socket.S: Add unwind information.
Diffstat (limited to 'nptl/sysdeps/unix/sysv/linux/sh')
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h13
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S17
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S42
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S35
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S4
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S417
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S464
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S103
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S35
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h102
10 files changed, 931 insertions, 301 deletions
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h b/nptl/sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h
index 3a80ec8e14..76d22c88f9 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h
+++ b/nptl/sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 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
@@ -20,6 +20,7 @@
 
 #define _IMP1 #1
 #define _IMM1 #-1
+#define _IMM4 #-4
 #define _IMM6 #-6
 #define _IMM8 #-8
 
@@ -53,6 +54,16 @@
 	mov.l	reg, mem; \
 99:	mov	r1, r15
 
+#define	XCHG(reg, mem, old) \
+	.align	2; \
+	mova	99f, r0; \
+	nop; \
+	mov	r15, r1; \
+	mov	_IMM4, r15; \
+98:	mov.l	mem, old; \
+	mov.l	reg, mem; \
+99:	mov	r1, r15
+
 #define	CMPXCHG(reg, mem, new, old) \
 	.align	2; \
 	mova	99f, r0; \
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S
index 936a4e3868..320fe18fe8 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S
+++ b/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 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
@@ -38,17 +38,12 @@ __lll_mutex_lock_wait:
 	mov	r5, r8
 	mov	#0, r7		/* No timeout.  */
 	mov	#FUTEX_WAIT, r5
-1:
+
 	mov	#2, r4
 	cmp/eq	r4, r6
-	bt	3f
-
-	mov	#1, r3
-	CMPXCHG (r3, @r8, r4, r2)
-	tst	r2, r2
-	bt	2f
+	bf	2f
 
-3:
+1:
 	mov	r8, r4
 	mov	#SYS_futex, r3
 	extu.b	r3, r3
@@ -56,9 +51,9 @@ __lll_mutex_lock_wait:
 	SYSCALL_INST_PAD
 
 2:
-	mov	#0, r3
 	mov	#2, r4
-	CMPXCHG (r3, @r8, r4, r2)
+	XCHG (r4, @r8, r2)
+	tst	r2, r2
 	bf	1b
 
 	mov.l	@r15+, r8
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S
index 6696898c18..1fbb23a5a6 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S
+++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 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
@@ -80,6 +80,23 @@ pthread_barrier_wait:
 	cmp/eq	r0, r6
 	bt	8b
 
+	/* Increment LEFT.  If this brings the count back to the
+	   initial count unlock the object.  */
+	mov	#1, r3
+	mov.l	@(INIT_COUNT,r8), r4
+	XADD	(r3, @(LEFT,r8), r2)
+	add	#-1, r4
+	cmp/eq	r2, r4
+	bf	10f
+
+	/* Release the mutex.  We cannot release the lock before
+	   waking the waiting threads since otherwise a new thread might
+	   arrive and gets waken up, too.  */
+	DEC (@(MUTEX,r8), r2)
+	tst	r2, r2
+	bf	9f
+
+10:
 	mov	#0, r0		/* != PTHREAD_BARRIER_SERIAL_THREAD */
 	lds.l	@r15+, pr
 	mov.l	@r15+, r8
@@ -88,8 +105,6 @@ pthread_barrier_wait:
 
 3:
 	/* The necessary number of threads arrived.  */
-	mov.l	@(INIT_COUNT,r8), r0
-	mov.l	r0, @(LEFT,r8)
 	mov.l	@(CURR_EVENT,r8), r1
 	add	#1, r1
 	mov.l	r1, @(CURR_EVENT,r8)
@@ -108,6 +123,15 @@ pthread_barrier_wait:
 	trapa	#0x14
 	SYSCALL_INST_PAD
 
+	/* Increment LEFT.  If this brings the count back to the
+	   initial count unlock the object.  */
+	mov	#1, r3
+	mov.l	@(INIT_COUNT,r8), r4
+	XADD	(r3, @(LEFT,r8), r2)
+	add	#-1, r4
+	cmp/eq	r2, r4
+	bf	5f
+
 	/* Release the mutex.  */
 	DEC (@(MUTEX,r8), r2)
 	tst	r2, r2
@@ -148,6 +172,16 @@ pthread_barrier_wait:
 	bra	7b
 	 mov	r9, r6
 
+9:	
+	mov	r6, r9
+	mov	r8, r4
+	mov.l	.Lwake2, r1
+	bsrf	r1
+	 add	#MUTEX, r4
+.Lwake2b:
+	bra	10b
+	 mov	r9, r6
+
 	.align	2
 .Lall:
 	.long	0x7fffffff
@@ -157,4 +191,6 @@ pthread_barrier_wait:
 	.long	__lll_mutex_unlock_wake-.Lwake0b
 .Lwake1:
 	.long	__lll_mutex_unlock_wake-.Lwake1b
+.Lwake2:
+	.long	__lll_mutex_unlock_wake-.Lwake2b
 	.size	pthread_barrier_wait,.-pthread_barrier_wait
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S
index 5bcaec09c0..a433ba3c37 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S
+++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 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
@@ -79,11 +79,16 @@ __pthread_cond_broadcast:
 #endif
 	tst	r2, r2
 	bf	7f
+
 8:
-	/* Wake up all threads.  */
+	/* Don't use requeue for pshared condvars.  */
+	mov	#-1, r0
+	cmp/eq	r0, r9
 	mov	r8, r4
-	add	#wakeup_seq, r4
-#ifdef __ASSUME_FUTEX_REQUEUE
+	bt/s	9f
+	 add	#wakeup_seq, r4
+
+	/* Wake up all threads.  */
 	mov	#FUTEX_REQUEUE, r5
 	mov	#1, r6
 	mov	#-1, r7
@@ -95,17 +100,9 @@ __pthread_cond_broadcast:
 	mov	#SYS_futex, r3
 	extu.b	r3, r3
 	trapa	#0x15
-#else
-	mov	#FUTEX_WAKE, r5
-	mov	#-1, r6
-	shlr	r6		/* r6 = 0x7fffffff */
-	mov	#0, r7
-	mov	#SYS_futex, r3
-	extu.b	r3, r3
-	trapa	#0x14
-#endif
 	SYSCALL_INST_PAD
 
+10:
 	mov	#0, r0
 	lds.l	@r15+, pr
 	mov.l	@r15+, r8
@@ -167,6 +164,18 @@ __pthread_cond_broadcast:
 	bra	8b
 	 nop
 
+9:
+	mov	#FUTEX_WAKE, r5
+	mov	#-1, r6
+	shlr	r6		/* r6 = 0x7fffffff */
+	mov	#0, r7
+	mov	#SYS_futex, r3
+	extu.b	r3, r3
+	trapa	#0x14
+	SYSCALL_INST_PAD
+	bra	10b
+	 nop
+
 	.align	2
 .Lmwait5:
 	.long	__lll_mutex_lock_wait-.Lmwait5b
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S
index 1a3a3485da..a0d188abb2 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S
+++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 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
@@ -73,7 +73,7 @@ __pthread_cond_signal:
 	mov.l	r0,@(wakeup_seq,r8)
 	mov.l	r1,@(wakeup_seq+4,r8)
 
-	/* Wake up one thread by moving it to the internal lock futex.  */
+	/* Wake up one thread.  */
 	mov	r8, r4
 	add	#wakeup_seq, r4
 	mov	#FUTEX_WAKE, r5
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S
index 278f695b6e..661caa3fb5 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S
+++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 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
@@ -36,17 +36,31 @@
 	.type	__pthread_cond_timedwait, @function
 	.align	5
 __pthread_cond_timedwait:
+.LSTARTCODE:
 	mov.l	r8, @-r15
+.Lpush_r8:
 	mov.l	r9, @-r15
+.Lpush_r9:
 	mov.l	r10, @-r15
+.Lpush_r10:
 	mov.l	r11, @-r15
+.Lpush_r11:
 	mov.l	r12, @-r15
+.Lpush_r12:
 	mov.l	r13, @-r15
+.Lpush_r13:
 	sts.l	pr, @-r15
+.Lpush_pr:
 	add	#-64, r15
+.Lalloc:
 	mov	r4, r8
 	mov	r5, r9
 	mov	r6, r13
+#ifdef PIC
+	mova	.Lgot0, r0
+	mov.l	.Lgot0, r12
+	add	r0, r12
+#endif
 
 	/* Get internal lock.  */
 	mov	#0, r3
@@ -59,11 +73,21 @@ __pthread_cond_timedwait:
 	bt	2f
 	bra	1f
 	 nop
+#ifdef PIC
+	.align	2
+.Lgot0:
+	.long	_GLOBAL_OFFSET_TABLE_
+#endif
+
 2:
 	/* Store the reference to the mutex.  If there is already a
 	   different value in there this is a bad user bug.  */
+	mov.l	@(dep_mutex,r8),r0
+	cmp/eq	#-1, r0
+	bt	17f
 	mov.l	r9, @(dep_mutex,r8)
-	
+
+17:	
 	/* Unlock the mutex.  */
 	mov.l	.Lmunlock1, r1
 	mov	#0, r5
@@ -87,50 +111,11 @@ __pthread_cond_timedwait:
 	mov.l	r0,@(total_seq,r8)
 	mov.l	r1,@(total_seq+4,r8)
 
-	/* Install cancellation handler.  */
-#ifdef PIC
-	mova	.Lgot1, r0
-	mov.l	.Lgot1, r12
-	add	r0, r12
-	mov.l	.Lccleanup1, r5
-	add	r12, r5
-#else
-	mov.l	.Lccleanup1, r5
-#endif
-	mov	r15, r4
-	add	#32, r4
-
-	/* Prepare structure passed to cancellation handler.  */
-	mov.l	r8, @(4,r15)
-	mov.l	r9, @(8,r15)
-
-	mov.l	.Lccpush1, r1
-	bsrf	r1
-	 mov	r15, r6
-.Lccpush1b:
-
 	/* Get and store current wakeup_seq value.  */
 	mov.l	@(wakeup_seq,r8), r10
 	mov.l	@(wakeup_seq+4,r8), r11
 
-	/* Unlock.  */
-8:
-#if cond_lock != 0
-	DEC (@(cond_lock,r8), r2)
-#else
-	DEC (@r8, r2)
-#endif
-	tst	r2, r2
-	bt	4f
-	bra	3f
-	 nop
-4:
-	mov.l	.Lenable1, r1
-	bsrf	r1
-	 nop
-.Lenable1b:
-	mov.l	r0, @r15
-
+8:	
 	/* Get current time.  */
 	mov	r15, r4
 	add	#16, r4
@@ -162,6 +147,24 @@ __pthread_cond_timedwait:
 	mov.l	r2, @(16,r15)
 	mov.l	r3, @(20,r15)
 
+	/* Unlock.  */
+#if cond_lock != 0
+	DEC (@(cond_lock,r8), r2)
+#else
+	DEC (@r8, r2)
+#endif
+	tst	r2, r2
+	bt	4f
+	bra	3f
+	 nop
+4:
+.LcleanupSTART:
+	mov.l	.Lenable1, r1
+	bsrf	r1
+	 nop
+.Lenable1b:
+	mov.l	r0, @r15
+
 	mov	r15, r7
 	add	#16, r7
 	mov	#FUTEX_WAIT, r5
@@ -178,6 +181,7 @@ __pthread_cond_timedwait:
 	bsrf	r1
 	 mov.l	@r15, r4
 .Ldisable1b:
+.LcleanupEND:
 
 	/* Lock.  */
 	mov	#0, r3
@@ -195,20 +199,15 @@ __pthread_cond_timedwait:
 	mov.l	@(wakeup_seq,r8), r2
 	mov.l	@(wakeup_seq+4,r8), r3
 
-	cmp/hi	r11, r3
-	bt	7f
-	cmp/hi	r3, r11
-	bt	15f
-
-	cmp/hs	r2, r10
+	cmp/eq	r3, r11
+	bf	7f
+	cmp/eq	r2, r10
 	bt	15f
 7:
-	cmp/hi	r1, r3
-	bt	9f
-	cmp/hi	r3, r1
-	bt	15f
-	cmp/hi	r0, r2
-	bt	9f
+	cmp/eq	r1, r3
+	bf	9f
+	cmp/eq	r0, r2
+	bf	9f
 15:
 	mov.l	@(12,r15),r0
 	cmp/eq	#-ETIMEDOUT, r0
@@ -252,14 +251,6 @@ __pthread_cond_timedwait:
 	bf	10f
 
 11:
-	/* Remove cancellation handler.  */
-	mov	r15, r4
-	add	#32, r4
-	mov.l	.Lcpop1, r1
-	bsrf	r1
-	 mov	#0, r5
-.Lcpop1b:
-
 	mov	r9, r4
 	mov.l	.Lmlocki1, r1
 	bsrf	r1
@@ -273,44 +264,39 @@ __pthread_cond_timedwait:
 
 18:	
 	add	#64, r15
+.Lfree:	
 	lds.l	@r15+, pr
+.Lpop_pr:
 	mov.l	@r15+, r13
+.Lpop_r13:
 	mov.l	@r15+, r12
+.Lpop_r12:
 	mov.l	@r15+, r11
+.Lpop_r11:
 	mov.l	@r15+, r10
+.Lpop_r10:
 	mov.l	@r15+, r9
+.Lpop_r9:
 	rts
 	 mov.l	@r15+, r8
-	ret
+.Lpop_r8:
 
 .L1k:
 	.word	1000
 	.align	2
 .Lmunlock1:
 	.long	__pthread_mutex_unlock_usercnt-.Lmunlock1b
-#ifdef PIC
-.Lgot1:
-	.long	_GLOBAL_OFFSET_TABLE_
-.Lccleanup1:
-	.long	__condvar_cleanup@GOTOFF
-#else
-.Lccleanup1:
-	.long	__condvar_cleanup
-#endif
-.Lccpush1:
-	.long	__pthread_cleanup_push-.Lccpush1b
 .Lenable1:
 	.long	__pthread_enable_asynccancel-.Lenable1b
 .Ldisable1:
 	.long	__pthread_disable_asynccancel-.Ldisable1b
-.Lcpop1:
-	.long	__pthread_cleanup_pop-.Lcpop1b
 .Lmlocki1:
 	.long	__pthread_mutex_cond_lock-.Lmlocki1b
 .L1g:
 	.long	1000000000
 
 1:
+.LSblSTART:
 	/* Initial locking failed.  */
 	mov	r8, r5
 #if cond_lock != 0
@@ -384,6 +370,7 @@ __pthread_cond_timedwait:
 17:
 	bra	18b
 	 mov.l	@(24,r15), r0
+.LSblEND:
 
 	.align	2
 .Lmwait2:
@@ -399,3 +386,281 @@ __pthread_cond_timedwait:
 	.size	__pthread_cond_timedwait, .-__pthread_cond_timedwait
 versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
 		  GLIBC_2_3_2)
+
+
+	.type	__condvar_tw_cleanup, @function
+__condvar_tw_cleanup:
+	mov	r4, r11
+
+	/* Get internal lock.  */
+	mov	#0, r3
+	mov	#1, r4
+#if cond_lock != 0
+	CMPXCHG (r3, @(cond_lock,r8), r4, r2)
+#else
+	CMPXCHG (r3, @r8, r4, r2)
+#endif
+	bt	1f
+	 nop
+
+	mov	r8, r5
+#if cond_lock != 0
+	add	#cond_lock, r5
+#endif
+	mov.l	.Lmwait5, r1
+	bsrf	r1
+	 mov	r2, r4
+.Lmwait5b:
+
+1:
+	mov	#1, r2
+	mov	#0, r3
+
+	clrt
+	mov.l	@(wakeup_seq,r8),r0
+	mov.l	@(wakeup_seq+4,r8),r1
+	addc	r2, r0
+	addc	r3, r1
+	mov.l	r0,@(wakeup_seq,r8)
+	mov.l	r1,@(wakeup_seq+4,r8)
+
+#if cond_lock != 0
+	DEC (@(cond_lock,r8), r2)
+#else
+	DEC (@r8, r2)
+#endif
+	tst	r2, r2
+	bt	2f
+
+	mov	r8, r4
+#if cond_lock != 0
+	add	#cond_lock, r4
+#endif
+	mov.l	.Lmwake5, r1
+	bsrf	r1
+	 nop
+.Lmwake5b:
+
+2:
+	/* Wake up all waiters to make sure no signal gets lost.  */
+	mov	r8, r4
+	add	#wakeup_seq, r4
+	mov	#FUTEX_WAKE, r5
+	mov	#-1, r6
+	shlr	r6		/* r6 = 0x7fffffff */
+	mov	#0, r7
+	mov	#SYS_futex, r3
+	extu.b	r3, r3
+	trapa	#0x14
+	SYSCALL_INST_PAD
+
+        mov.l   .Lmlocki5, r1
+        bsrf    r1
+         mov     r9, r4
+.Lmlocki5b:
+
+.LcallUR:
+	mov.l	.Lresume, r1
+#ifdef PIC
+	add	r12, r1
+#endif
+	jsr	@r1
+	 mov	r11, r4
+	sleep
+
+	.align	2
+.Lmwait5:
+	.long   __lll_mutex_lock_wait-.Lmwait5b
+.Lmwake5:
+        .long   __lll_mutex_unlock_wake-.Lmwake5b
+.Lmlocki5:
+	.long   __pthread_mutex_cond_lock-.Lmlocki5b
+.Lresume:
+#ifdef PIC
+	.long	_Unwind_Resume@GOTOFF
+#else
+	.long	_Unwind_Resume
+#endif
+.LENDCODE:
+	.size	__condvar_tw_cleanup, .-__condvar_tw_cleanup
+
+
+	.section .gcc_except_table,"a",@progbits
+.LexceptSTART:
+	.byte	0xff				! @LPStart format (omit)
+	.byte	0xff				! @TType format (omit)
+	.byte	0x0b				! call-site format
+						! DW_EH_PE_sdata4
+	.uleb128 .Lcstend-.Lcstbegin
+.Lcstbegin:
+	.ualong	.LcleanupSTART-.LSTARTCODE
+	.ualong	.LcleanupEND-.LcleanupSTART
+	.ualong	__condvar_tw_cleanup-.LSTARTCODE
+	.uleb128  0
+	.ualong	.LcallUR-.LSTARTCODE
+	.ualong	.LENDCODE-.LcallUR
+	.ualong	0
+	.uleb128  0
+.Lcstend:
+
+	.section .eh_frame,"a",@progbits
+.LSTARTFRAME:
+	.ualong	.LENDCIE-.LSTARTCIE		! Length of the CIE.
+.LSTARTCIE:
+	.ualong	0				! CIE ID.
+	.byte	1				! Version number.
+#ifdef SHARED
+	.string	"zPLR"				! NUL-terminated augmentation
+						! string.
+#else
+	.string	"zPL"				! NUL-terminated augmentation
+						! string.
+#endif
+	.uleb128 1				! Code alignment factor.
+	.sleb128 -4				! Data alignment factor.
+	.byte	0x11				! Return address register
+						! column.
+#ifdef SHARED
+	.uleb128 7				! Augmentation value length.
+	.byte	0x9b				! Personality: DW_EH_PE_pcrel
+						! + DW_EH_PE_sdata4
+						! + DW_EH_PE_indirect
+	.ualong	DW.ref.__gcc_personality_v0-.
+	.byte	0x1b				! LSDA Encoding: DW_EH_PE_pcrel
+						! + DW_EH_PE_sdata4.
+	.byte	0x1b				! FDE Encoding: DW_EH_PE_pcrel
+						! + DW_EH_PE_sdata4.
+#else
+	.uleb128 6				! Augmentation value length.
+	.byte	0x0				! Personality: absolute
+	.ualong	__gcc_personality_v0
+	.byte	0x0				! LSDA Encoding: absolute
+#endif
+	.byte 0x0c				! DW_CFA_def_cfa
+	.uleb128 0xf
+	.uleb128 0
+	.align 2
+.LENDCIE:
+
+	.ualong	.LENDFDE-.LSTARTFDE		! Length of the FDE.
+.LSTARTFDE:
+	.ualong	.LSTARTFDE-.LSTARTFRAME		! CIE pointer.
+#ifdef SHARED
+	.ualong	.LSTARTCODE-.			! PC-relative start address
+						! of the code.
+#else
+	.ualong	.LSTARTCODE			! Start address of the code.
+#endif
+	.ualong	.LENDCODE-.LSTARTCODE		! Length of the code.
+	.uleb128 4				! Augmentation size
+#ifdef SHARED
+	.ualong	.LexceptSTART-.
+#else
+	.ualong	.LexceptSTART
+#endif
+	.byte	0x4
+	.ualong	.Lpush_r8-.LSTARTCODE
+	.byte	0xe
+	.uleb128 4
+	.byte	0x88
+	.uleb128 1
+	.byte	0x4
+	.ualong	.Lpush_r9-.Lpush_r8
+	.byte	0xe
+	.uleb128 8
+	.byte	0x89
+	.uleb128 2
+	.byte	0x4
+	.ualong	.Lpush_r10-.Lpush_r9
+	.byte	0xe
+	.uleb128 12
+	.byte	0x8a
+	.uleb128 3
+	.byte	0x4
+	.ualong	.Lpush_r11-.Lpush_r10
+	.byte	0xe
+	.uleb128 16
+	.byte	0x8b
+	.uleb128 4
+	.byte	0x4
+	.ualong	.Lpush_r12-.Lpush_r11
+	.byte	0xe
+	.uleb128 20
+	.byte	0x8c
+	.uleb128 5
+	.byte	0x4
+	.ualong	.Lpush_r13-.Lpush_r12
+	.byte	0xe
+	.uleb128 24
+	.byte	0x8d
+	.uleb128 6
+	.byte	0x4
+	.ualong	.Lpush_pr-.Lpush_r13
+	.byte	0xe
+	.uleb128 28
+	.byte	0x91
+	.uleb128 7
+	.byte	0x4
+	.ualong	.Lalloc-.Lpush_pr
+	.byte	0xe
+	.uleb128 92
+	.byte	0x4
+	.ualong	.Lfree-.Lalloc
+	.byte	0xe
+	.uleb128 28
+	.byte	0x4
+	.ualong	.Lpop_pr-.Lfree
+	.byte	0xe
+	.uleb128 24
+	.byte	0xd1
+	.byte	0x4
+	.ualong	.Lpop_r13-.Lpop_pr
+	.byte	0xe
+	.uleb128 20
+	.byte	0xcd
+	.byte	0x4
+	.ualong	.Lpop_r12-.Lpop_r13
+	.byte	0xe
+	.uleb128 16
+	.byte	0xcc
+	.byte	0x4
+	.ualong	.Lpop_r11-.Lpop_r12
+	.byte	0xe
+	.uleb128 12
+	.byte	0xcb
+	.byte	0x4
+	.ualong	.Lpop_r10-.Lpop_r11
+	.byte	0xe
+	.uleb128 8
+	.byte	0xca
+	.byte	0x4
+	.ualong	.Lpop_r9-.Lpop_r10
+	.byte	0xe
+	.uleb128 4
+	.byte	0xc9
+	.byte	0x4
+	.ualong	.Lpop_r8-.Lpop_r9
+	.byte	0xe
+	.uleb128 0
+	.byte	0xc8
+	.byte	0x4
+	.ualong	.LSblSTART-.Lpop_r8
+	.byte	0xe
+	.uleb128 72
+	.byte	0x4
+	.ualong	.LSblEND-.LSblSTART
+	.byte	0xe
+	.uleb128 72
+	.align	2
+.LENDFDE:
+
+#ifdef SHARED
+	.hidden DW.ref.__gcc_personality_v0
+	.weak   DW.ref.__gcc_personality_v0
+	.section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
+	.align 4
+	.type   DW.ref.__gcc_personality_v0, @object
+	.size   DW.ref.__gcc_personality_v0, 4
+DW.ref.__gcc_personality_v0:
+	.long   __gcc_personality_v0
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S
index a1967f4922..01b906eeed 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S
+++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 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
@@ -28,119 +28,33 @@
 
 	.text
 
-	.align	5
-	.type	__condvar_cleanup, @function
-	.globl	__condvar_cleanup
-	.hidden	__condvar_cleanup
-__condvar_cleanup:
-	mov.l	r8, @-r15
-	mov.l	r9, @-r15
-	sts.l	pr, @-r15
-	mov	r4, r9
-	mov.l	@(4,r9), r8
-
-	/* Get internal lock.  */
-	mov	#0, r3
-	mov	#1, r4
-#if cond_lock != 0
-	CMPXCHG (r3, @(cond_lock,r8), r4, r2)
-#else
-	CMPXCHG (r3, @r8, r4, r2)
-#endif
-	bt	1f
-	mov	r8, r5
-#if cond_lock != 0
-	add	#cond_lock, r5
-#endif
-	mov.l	.Lwait0, r1
-	bsrf	r1
-	 mov	r2, r4
-.Lwait0b:
-1:
-	mov	#1, r2
-	mov	#0, r3
-
-	clrt
-	mov.l	@(wakeup_seq,r8),r0
-	mov.l	@(wakeup_seq+4,r8),r1
-	addc	r2, r0
-	addc	r3, r1
-	mov.l	r0,@(wakeup_seq,r8)
-	mov.l	r1,@(wakeup_seq+4,r8)
-
-	clrt
-	mov.l	@(woken_seq,r8),r0
-	mov.l	@(woken_seq+4,r8),r1
-	addc	r2, r0
-	addc	r3, r1
-	mov.l	r0,@(woken_seq,r8)
-	mov.l	r1,@(woken_seq+4,r8)
-
-	/* Release internal lock.  */
-#if cond_lock != 0
-	DEC (@(cond_lock,r8), r2)
-#else
-	DEC (@r8, r2)
-#endif
-	tst	r2, r2
-	bt	2f
-
-	mov	r8, r4
-#if cond_lock != 0
-	add	#cond_lock, r4
-#endif
-	mov.l	.Lwake0, r1
-	bsrf	r1
-	 nop
-.Lwake0b:
-2:
-
-	/* Wake up all waiters to make sure no signal gets lost.  */
-	mov	r8, r4
-	add	#wakeup_seq, r4
-	mov	#FUTEX_WAKE, r5
-	mov	#-1, r6
-	shlr	r6		/* r6 = 0x7fffffff */
-	mov	#0, r7
-	mov	#SYS_futex, r3
-	extu.b	r3, r3
-	trapa	#0x14
-	SYSCALL_INST_PAD
-
-	mov.l	.Lmlocki1, r1
-	bsrf	r1
-	 mov.l	@(8,r9), r4
-.Lmlocki1b:
-
-	lds.l	@r15+, pr
-	mov.l	@r15+, r9
-	rts
-	 mov.l	@r15+, r8
-
-	.align	2
-.Lwait0:	
-	.long	__lll_mutex_lock_wait-.Lwait0b
-.Lwake0:
-	.long	__lll_mutex_unlock_wake-.Lwake0b
-.Lmlocki1:
-	.long	__pthread_mutex_cond_lock-.Lmlocki1b
-	.size	__condvar_cleanup, .-__condvar_cleanup
-
-
 /* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)  */
 	.globl	__pthread_cond_wait
 	.type	__pthread_cond_wait, @function
 	.align	5
 __pthread_cond_wait:
+.LSTARTCODE:
 	mov.l	r8, @-r15
+.Lpush_r8:
 	mov.l	r9, @-r15
+.Lpush_r9:
 	mov.l	r10, @-r15
+.Lpush_r10:
 	mov.l	r11, @-r15
+.Lpush_r11:
 	mov.l	r12, @-r15
+.Lpush_r12:
 	sts.l	pr, @-r15
+.Lpush_pr:
 	add	#-48, r15
+.Lalloc:
 	mov	r4, r8
 	mov	r5, r9
+#ifdef PIC
+	mova	.Lgot0, r0
+	mov.l	.Lgot0, r12
+	add	r0, r12
+#endif
 
 	/* Get internal lock.  */
 	mov	#0, r3
@@ -153,12 +67,21 @@ __pthread_cond_wait:
 	bt	2f
 	bra	1f
 	 nop
+#ifdef PIC
+	.align	2
+.Lgot0:
+	.long	_GLOBAL_OFFSET_TABLE_
+#endif
 
 2:	
 	/* Store the reference to the mutex.  If there is already a
 	   different value in there this is a bad user bug.  */
+	mov.l	@(dep_mutex,r8),r0
+	cmp/eq	#-1, r0
+	bt	15f
 	mov.l	r9, @(dep_mutex,r8)
 
+15:	
 	/* Unlock the mutex.  */
 	mov.l	.Lmunlock0, r1
 	mov	#0, r5
@@ -182,28 +105,6 @@ __pthread_cond_wait:
 	mov.l	r0,@(total_seq,r8)
 	mov.l	r1,@(total_seq+4,r8)
 
-	/* Install cancellation handler.  */
-#ifdef PIC
-	mova	.Lgot0, r0
-	mov.l	.Lgot0, r12
-	add	r0, r12
-	mov.l	.Lccleanup0, r5
-	add	r12, r5
-#else
-	mov.l	.Lccleanup0, r5
-#endif
-	mov	r15, r4
-	add	#16, r4
-
-	/* Prepare structure passed to cancellation handler.  */
-	mov.l	r8, @(4,r15)
-	mov.l	r9, @(8,r15)
-
-	mov.l	.Lccpush0, r1
-	bsrf	r1
-	 mov	r15, r6
-.Lccpush0b:
-
 	/* Get and store current wakeup_seq value.  */
 	mov.l	@(wakeup_seq,r8), r10
 	mov.l	@(wakeup_seq+4,r8), r11
@@ -218,6 +119,7 @@ __pthread_cond_wait:
 	tst	r2, r2
 	bf	3f
 4:
+.LcleanupSTART:
 	mov.l	.Lenable0, r1
 	bsrf	r1
 	 nop
@@ -238,6 +140,7 @@ __pthread_cond_wait:
 	bsrf	r1
 	 mov.l	@r15, r4
 .Ldisable0b:	
+.LcleanupEND:
 
 	/* Lock.  */
 	mov	#0, r3
@@ -255,20 +158,15 @@ __pthread_cond_wait:
 	mov.l	@(wakeup_seq,r8), r2
 	mov.l	@(wakeup_seq+4,r8), r3
 
-	cmp/hi	r11, r3
-	bt	7f
-	cmp/hi	r3, r11
-	bt	8b
-
-	cmp/hs	r2, r10
+	cmp/eq	r3, r11
+	bf	7f
+	cmp/eq	r2, r10
 	bt	8b
 7:
-	cmp/hi	r1, r3
-	bt	9f
-	cmp/hi	r3, r1
+	cmp/eq	r1, r3
+	bf	9f
+	cmp/eq	r0, r2
 	bt	8b
-	cmp/hi	r0, r2
-	bf	8b
 9:
 	mov	#1, r2
 	mov	#0, r3
@@ -290,55 +188,41 @@ __pthread_cond_wait:
 	bf	10f
 
 11:
-	/* Remove cancellation handler.  */
-	mov	r15, r4
-	add	#16, r4
-	mov.l	.Lcpop0, r1
-	bsrf	r1
-	 mov	#0, r5
-.Lcpop0b:
-
-	mov	r9, r4
 	mov.l	.Lmlocki0, r1
 	bsrf	r1
-	 nop
+	 mov	r9, r4
 .Lmlocki0b:
 	/* We return the result of the mutex_lock operation.  */
 
 14:
 	add	#48, r15
+.Lfree:	
 	lds.l	@r15+, pr
+.Lpop_pr:
 	mov.l	@r15+, r12
+.Lpop_r12:
 	mov.l	@r15+, r11
+.Lpop_r11:
 	mov.l	@r15+, r10
+.Lpop_r10:
 	mov.l	@r15+, r9
+.Lpop_r9:
 	rts
 	 mov.l	@r15+, r8
+.Lpop_r8:
 
 	.align	2
 .Lmunlock0:
 	.long	__pthread_mutex_unlock_usercnt-.Lmunlock0b
-#ifdef PIC
-.Lgot0:
-	.long	_GLOBAL_OFFSET_TABLE_
-.Lccleanup0:
-	.long	__condvar_cleanup@GOTOFF
-#else
-.Lccleanup0:
-	.long	__condvar_cleanup
-#endif
-.Lccpush0:
-	.long	__pthread_cleanup_push-.Lccpush0b
 .Lenable0:
 	.long	__pthread_enable_asynccancel-.Lenable0b
 .Ldisable0:
 	.long	__pthread_disable_asynccancel-.Ldisable0b
-.Lcpop0:
-	.long	__pthread_cleanup_pop-.Lcpop0b
 .Lmlocki0:
 	.long	__pthread_mutex_cond_lock-.Lmlocki0b
 
 1:
+.LSblSTART:
 	/* Initial locking failed.  */
 	mov	r8, r5
 #if cond_lock != 0
@@ -412,6 +296,7 @@ __pthread_cond_wait:
 13:
 	bra	14b
 	 mov.l	@(12,r15), r0
+.LSblEND:
 
 	.align	2
 .Lmwait0:
@@ -427,3 +312,270 @@ __pthread_cond_wait:
 	.size	__pthread_cond_wait, .-__pthread_cond_wait
 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
 		  GLIBC_2_3_2)
+
+
+	.type	__condvar_w_cleanup, @function
+__condvar_w_cleanup:
+	mov	r4, r11
+
+	/* Get internal lock.  */
+	mov	#0, r3
+	mov	#1, r4
+#if cond_lock != 0
+	CMPXCHG (r3, @(cond_lock,r8), r4, r2)
+#else
+	CMPXCHG (r3, @r8, r4, r2)
+#endif
+	bt	1f
+	 nop
+
+	mov	r8, r5
+#if cond_lock != 0
+	add	#cond_lock, r5
+#endif
+	mov.l	.Lmwait3, r1
+	bsrf	r1
+	 mov	r2, r4
+.Lmwait3b:
+
+1:
+	mov	#1, r2
+	mov	#0, r3
+
+	clrt
+	mov.l	@(wakeup_seq,r8),r0
+	mov.l	@(wakeup_seq+4,r8),r1
+	addc	r2, r0
+	addc	r3, r1
+	mov.l	r0,@(wakeup_seq,r8)
+	mov.l	r1,@(wakeup_seq+4,r8)
+
+#if cond_lock != 0
+	DEC (@(cond_lock,r8), r2)
+#else
+	DEC (@r8, r2)
+#endif
+	tst	r2, r2
+	bt	2f
+
+	mov	r8, r4
+#if cond_lock != 0
+	add	#cond_lock, r4
+#endif
+	mov.l	.Lmwake3, r1
+	bsrf	r1
+	 nop
+.Lmwake3b:
+
+2:
+	/* Wake up all waiters to make sure no signal gets lost.  */
+	mov	r8, r4
+	add	#wakeup_seq, r4
+	mov	#FUTEX_WAKE, r5
+	mov	#-1, r6
+	shlr	r6		/* r6 = 0x7fffffff */
+	mov	#0, r7
+	mov	#SYS_futex, r3
+	extu.b	r3, r3
+	trapa	#0x14
+	SYSCALL_INST_PAD
+
+        mov.l   .Lmlocki3, r1
+        bsrf    r1
+         mov     r9, r4
+.Lmlocki3b:
+
+.LcallUR:
+	mov.l	.Lresume, r1
+#ifdef PIC
+	add	r12, r1
+#endif
+	jsr	@r1
+	 mov	r11, r4
+	sleep
+
+	.align	2
+.Lmwait3:
+	.long   __lll_mutex_lock_wait-.Lmwait3b
+.Lmwake3:
+        .long   __lll_mutex_unlock_wake-.Lmwake3b
+.Lmlocki3:
+	.long   __pthread_mutex_cond_lock-.Lmlocki3b
+.Lresume:
+#ifdef PIC
+	.long	_Unwind_Resume@GOTOFF
+#else
+	.long	_Unwind_Resume
+#endif
+.LENDCODE:
+	.size	__condvar_w_cleanup, .-__condvar_w_cleanup
+
+
+	.section .gcc_except_table,"a",@progbits
+.LexceptSTART:
+	.byte	0xff				! @LPStart format (omit)
+	.byte	0xff				! @TType format (omit)
+	.byte	0x0b				! call-site format
+						! DW_EH_PE_sdata4
+	.uleb128 .Lcstend-.Lcstbegin
+.Lcstbegin:
+	.ualong	.LcleanupSTART-.LSTARTCODE
+	.ualong	.LcleanupEND-.LcleanupSTART
+	.ualong	__condvar_w_cleanup-.LSTARTCODE
+	.uleb128  0
+	.ualong	.LcallUR-.LSTARTCODE
+	.ualong	.LENDCODE-.LcallUR
+	.ualong	0
+	.uleb128  0
+.Lcstend:
+
+	.section .eh_frame,"a",@progbits
+.LSTARTFRAME:
+	.ualong	.LENDCIE-.LSTARTCIE		! Length of the CIE.
+.LSTARTCIE:
+	.ualong	0				! CIE ID.
+	.byte	1				! Version number.
+#ifdef SHARED
+	.string	"zPLR"				! NUL-terminated augmentation
+						! string.
+#else
+	.string	"zPL"				! NUL-terminated augmentation
+						! string.
+#endif
+	.uleb128 1				! Code alignment factor.
+	.sleb128 -4				! Data alignment factor.
+	.byte	0x11				! Return address register
+						! column.
+#ifdef SHARED
+	.uleb128 7				! Augmentation value length.
+	.byte	0x9b				! Personality: DW_EH_PE_pcrel
+						! + DW_EH_PE_sdata4
+						! + DW_EH_PE_indirect
+	.ualong	DW.ref.__gcc_personality_v0-.
+	.byte	0x1b				! LSDA Encoding: DW_EH_PE_pcrel
+						! + DW_EH_PE_sdata4.
+	.byte	0x1b				! FDE Encoding: DW_EH_PE_pcrel
+						! + DW_EH_PE_sdata4.
+#else
+	.uleb128 6				! Augmentation value length.
+	.byte	0x0				! Personality: absolute
+	.ualong	__gcc_personality_v0
+	.byte	0x0				! LSDA Encoding: absolute
+#endif
+	.byte 0x0c				! DW_CFA_def_cfa
+	.uleb128 0xf
+	.uleb128 0
+	.align 2
+.LENDCIE:
+
+	.ualong	.LENDFDE-.LSTARTFDE		! Length of the FDE.
+.LSTARTFDE:
+	.ualong	.LSTARTFDE-.LSTARTFRAME		! CIE pointer.
+#ifdef SHARED
+	.ualong	.LSTARTCODE-.			! PC-relative start address
+						! of the code.
+#else
+	.ualong	.LSTARTCODE			! Start address of the code.
+#endif
+	.ualong	.LENDCODE-.LSTARTCODE		! Length of the code.
+	.uleb128 4				! Augmentation size
+#ifdef SHARED
+	.ualong	.LexceptSTART-.
+#else
+	.ualong	.LexceptSTART
+#endif
+	.byte	0x4
+	.ualong	.Lpush_r8-.LSTARTCODE
+	.byte	0xe
+	.uleb128 4
+	.byte	0x88
+	.uleb128 1
+	.byte	0x4
+	.ualong	.Lpush_r9-.Lpush_r8
+	.byte	0xe
+	.uleb128 8
+	.byte	0x89
+	.uleb128 2
+	.byte	0x4
+	.ualong	.Lpush_r10-.Lpush_r9
+	.byte	0xe
+	.uleb128 12
+	.byte	0x8a
+	.uleb128 3
+	.byte	0x4
+	.ualong	.Lpush_r11-.Lpush_r10
+	.byte	0xe
+	.uleb128 16
+	.byte	0x8b
+	.uleb128 4
+	.byte	0x4
+	.ualong	.Lpush_r12-.Lpush_r11
+	.byte	0xe
+	.uleb128 20
+	.byte	0x8c
+	.uleb128 5
+	.byte	0x4
+	.ualong	.Lpush_pr-.Lpush_r12
+	.byte	0xe
+	.uleb128 24
+	.byte	0x91
+	.uleb128 6
+	.byte	0x4
+	.ualong	.Lalloc-.Lpush_pr
+	.byte	0xe
+	.uleb128 72
+	.byte	0x4
+	.ualong	.Lfree-.Lalloc
+	.byte	0xe
+	.uleb128 24
+	.byte	0x4
+	.ualong	.Lpop_pr-.Lfree
+	.byte	0xe
+	.uleb128 20
+	.byte	0xd1
+	.byte	0x4
+	.ualong	.Lpop_r12-.Lpop_pr
+	.byte	0xe
+	.uleb128 16
+	.byte	0xcc
+	.byte	0x4
+	.ualong	.Lpop_r11-.Lpop_r12
+	.byte	0xe
+	.uleb128 12
+	.byte	0xcb
+	.byte	0x4
+	.ualong	.Lpop_r10-.Lpop_r11
+	.byte	0xe
+	.uleb128 8
+	.byte	0xca
+	.byte	0x4
+	.ualong	.Lpop_r9-.Lpop_r10
+	.byte	0xe
+	.uleb128 4
+	.byte	0xc9
+	.byte	0x4
+	.ualong	.Lpop_r8-.Lpop_r9
+	.byte	0xe
+	.uleb128 0
+	.byte	0xc8
+	.byte	0x4
+	.ualong	.LSblSTART-.Lpop_r8
+	.byte	0xe
+	.uleb128 72
+	.byte	0x4
+	.ualong	.LSblEND-.LSblSTART
+	.byte	0xe
+	.uleb128 72
+	.align	2
+.LENDFDE:
+
+#ifdef SHARED
+	.hidden DW.ref.__gcc_personality_v0
+	.weak   DW.ref.__gcc_personality_v0
+	.section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
+	.align 4
+	.type   DW.ref.__gcc_personality_v0, @object
+	.size   DW.ref.__gcc_personality_v0, 4
+DW.ref.__gcc_personality_v0:
+	.long   __gcc_personality_v0
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S
index c292af02c0..9b583a8317 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S
+++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 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
@@ -16,6 +16,7 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#include <unwindbuf.h>
 #include <sysdep.h>
 #include "lowlevel-atomic.h"
 
@@ -29,6 +30,7 @@
 	.globl	__pthread_once
 	.type	__pthread_once,@function
 	.align	5
+	cfi_startproc
 __pthread_once:
 	mov.l	@r4, r0
 	tst	#2, r0
@@ -38,20 +40,27 @@ __pthread_once:
 
 1:
 	mov.l	r12, @-r15
+	cfi_adjust_cfa_offset (4)
+	cfi_rel_offset (r12, 0)
 	mov.l	r9, @-r15
+	cfi_adjust_cfa_offset (4)
+	cfi_rel_offset (r9, 0)
 	mov.l	r8, @-r15
+	cfi_adjust_cfa_offset (4)
+	cfi_rel_offset (r8, 0)
 	sts.l	pr, @-r15
+	cfi_adjust_cfa_offset (4)
+	cfi_rel_offset (pr, 0)
 	mov	r5, r8
+	mov	r4, r9
 
 	/* Not yet initialized or initialization in progress.
 	   Get the fork generation counter now.  */
 6:
 	mov.l	@r4, r1
-#ifdef PIC
 	mova	.Lgot, r0
 	mov.l	.Lgot, r12
 	add	r0, r12
-#endif
 
 5:
 	mov	r1, r0
@@ -97,9 +106,9 @@ __pthread_once:
 	 nop
 
 	.align	2
-#ifdef PIC
 .Lgot:
 	.long	_GLOBAL_OFFSET_TABLE_
+#ifdef PIC
 .Lfgen:	
 	.long	__fork_generation@GOTOFF
 #else
@@ -109,31 +118,40 @@ __pthread_once:
 
 3:
 	/* Call the initializer function after setting up the
-	   cancellation handler.  */
-	/* Allocate a _pthread_cleanup_buffer on stack.  */
-	add	#-16, r15
+	   cancellation handler.  Note that it is not possible here
+	   to use the unwind-based cleanup handling.  This would require
+	   that the user-provided function and all the code it calls
+	   is compiled with exceptions.  Unfortunately this cannot be
+	   guaranteed.  */
+	add	#-UNWINDBUFSIZE, r15
+	cfi_adjust_cfa_offset (UNWINDBUFSIZE)
+
+	mov.l	.Lsigsetjmp, r1
+	mov	#UWJMPBUF, r4
+	add	r15, r4
+	bsrf	r1
+	 mov	#0, r5
+.Lsigsetjmp0:
+	tst	r0, r0
+	bf	7f
 
-	/* Push the cleanup handler.  */
-	mov	r4, r9
-	mov	r15, r4
-	mov.l	.Lconce, r5
-#ifdef PIC
-	add	r12, r5
-#endif
 	mov.l	.Lcpush, r1
 	bsrf	r1
-	 mov	r9, r6
+	 mov	r15, r4
 .Lcpush0:
+
+	/* Call the user-provided initialization function.  */
 	jsr	@r8
 	 nop
 
 	/* Pop the cleanup handler.  */
-	mov	r15, r4
 	mov.l	.Lcpop, r1
 	bsrf	r1
-	 mov	#0, r5
+	 mov	r15, r4
 .Lcpop0:
-	add	#16, r15
+
+	add	#UNWINDBUFSIZE, r15
+	cfi_adjust_cfa_offset (-UNWINDBUFSIZE)
 
 	/* Sucessful run of the initializer.  Signal that we are done.  */
 	INC (@r9, r2)
@@ -150,24 +168,55 @@ __pthread_once:
 
 4:
 	lds.l	@r15+, pr
+	cfi_adjust_cfa_offset (-4)
+	cfi_restore (pr)
 	mov.l	@r15+, r8
+	cfi_adjust_cfa_offset (-4)
+	cfi_restore (r8)
 	mov.l	@r15+, r9
+	cfi_adjust_cfa_offset (-4)
+	cfi_restore (r9)
 	mov.l	@r15+, r12
+	cfi_adjust_cfa_offset (-4)
+	cfi_restore (r12)
 	rts
 	 mov	#0, r0
 
+7:
+	/* __sigsetjmp returned for the second time.  */
+	cfi_adjust_cfa_offset (UNWINDBUFSIZE+16)
+	cfi_offset (r12, -4)
+	cfi_offset (r9, -8)
+	cfi_offset (r8, -12)
+	cfi_offset (pr, -16)
+	mov	#0, r7
+	mov.l	r7, @r9
+	mov	r9, r4
+	mov	#FUTEX_WAKE, r5
+	mov	#-1, r6
+	shlr	r6		/* r6 = 0x7fffffff */
+	mov	#SYS_futex, r3
+	extu.b	r3, r3
+	trapa	#0x14
+	SYSCALL_INST_PAD
+
+	mov.l	.Lunext, r1
+	bsrf	r1
+	 mov	r15, r4
+.Lunext0:
+	/* NOTREACHED */
+	sleep
+	cfi_endproc
+
 	.align	2
-.Lconce:
-#ifdef PIC
-	.long	clear_once_control@GOTOFF
-#else
-	.long	clear_once_control
-#endif
+.Lsigsetjmp:
+	.long	__sigsetjmp@PLT-(.Lsigsetjmp0+2-.)
 .Lcpush:
-	.long	__pthread_cleanup_push - .Lcpush0	/* Note: no @PLT.  */
+	.long	HIDDEN_JUMPTARGET(__pthread_register_cancel)-.Lcpush0
 .Lcpop:
-	.long	__pthread_cleanup_pop - .Lcpop0		/* Note: no @PLT.  */
-
+	.long	HIDDEN_JUMPTARGET(__pthread_unregister_cancel)-.Lcpop0
+.Lunext:
+	.long	HIDDEN_JUMPTARGET(__pthread_unwind_next)-.Lunext0
 	.size	__pthread_once,.-__pthread_once
 
 	.globl	__pthread_once_internal
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S b/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S
index 8a55394c29..28f78b015e 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S
+++ b/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 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
@@ -33,6 +33,7 @@
 	.globl	__new_sem_wait
 	.type	__new_sem_wait,@function
 	.align	5
+	cfi_startproc
 __new_sem_wait:
 	/* First check for cancellation.  */
 	stc	gbr, r0
@@ -44,9 +45,17 @@ __new_sem_wait:
 	bt	5f
 
 	mov.l	r8, @-r15
+	cfi_adjust_cfa_offset(4)
+	cfi_rel_offset (r8, 0)
 	mov.l	r10, @-r15
+	cfi_adjust_cfa_offset(4)
+	cfi_rel_offset (r10, 0)
 	mov.l	r12, @-r15
+	cfi_adjust_cfa_offset(4)
+	cfi_rel_offset (r12, 0)
 	sts.l	pr, @-r15
+	cfi_adjust_cfa_offset(4)
+	cfi_rel_offset (pr, 0)
 	mov	r4, r8
 3:
 	mov.l	@r8, r0
@@ -57,12 +66,9 @@ __new_sem_wait:
 	mov	r0, r4
 	add	#-1, r3
 	CMPXCHG (r4, @r8, r3, r2)
-	bf	2b
-	lds.l	@r15+, pr
-	mov.l	@r15+, r12
-	mov.l	@r15+, r10
-	mov.l	@r15+, r8
-	rts
+	bf/s	2b
+	 mov	r2, r0
+	bra	9f
 	 mov	#0, r0
 
 1:
@@ -112,13 +118,21 @@ __new_sem_wait:
 .Lerrloc0b:
 	mov.l	r8, @r0
 #endif
+	mov	#-1, r0
+9:
 	lds.l	@r15+, pr
+	cfi_adjust_cfa_offset (-4)
+	cfi_restore (pr)
 	mov.l	@r15+, r12
+	cfi_adjust_cfa_offset (-4)
+	cfi_restore (r12)
 	mov.l	@r15+, r10
-	mov.l	@r15+, r8
+	cfi_adjust_cfa_offset (-4)
+	cfi_restore (r10)
 	rts
-	 mov	#-1, r0
-
+	 mov.l	@r15+, r8
+	cfi_adjust_cfa_offset (-4)
+	cfi_restore (r8)
 5:
 	/* Canceled.  */
 	stc	gbr, r0
@@ -132,6 +146,7 @@ __new_sem_wait:
 	mov.l	.Lunwind, r2
 	jmp	@r2
 	 mov.l	@(r0,r1), r4
+	cfi_endproc
 
 .Lchand:
 	.word	CANCELHANDLING - TLS_PRE_TCB_SIZE
diff --git a/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h
index ba2efbcba9..581046c007 100644
--- a/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h
+++ b/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 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
@@ -31,6 +31,7 @@
 # define PSEUDO(name, syscall_name, args) \
   .text; \
   ENTRY (name); \
+  .Lpseudo_start: \
     SINGLE_THREAD_P; \
     bf .Lpseudo_cancel; \
     .type __##syscall_name##_nocancel,@function; \
@@ -48,19 +49,27 @@
     .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \
  .Lpseudo_cancel: \
     sts.l pr,@-r15; \
+ .LCFI0: \
     add _IMM16,r15; \
     SAVE_ARGS_##args; \
+ .LCFI1: \
     CENABLE; \
     LOAD_ARGS_##args; \
     add _IMP16,r15; \
+ .LCFI2: \
     lds.l @r15+,pr; \
+ .LCFI3: \
     DO_CALL(syscall_name, args); \
     SYSCALL_INST_PAD; \
     sts.l pr,@-r15; \
+ .LCFI4: \
     mov.l r0,@-r15; \
+ .LCFI5: \
     CDISABLE; \
     mov.l @r15+,r0; \
+ .LCFI6: \
     lds.l @r15+,pr; \
+ .LCFI7: \
     mov r0,r1; \
     mov _IMM12,r2; \
     shad r2,r1; \
@@ -69,7 +78,96 @@
     bf .Lpseudo_end; \
  .Lsyscall_error: \
     SYSCALL_ERROR_HANDLER; \
- .Lpseudo_end:
+ .Lpseudo_end: \
+ /* Create unwinding information for the syscall wrapper.  */ \
+ .section .eh_frame,"a",@progbits; \
+ .Lframe1: \
+    .ualong .LECIE1-.LSCIE1; \
+ .LSCIE1: \
+    .ualong 0x0; \
+    .byte   0x1; \
+    AUGMENTATION_STRING; \
+    .uleb128 0x1; \
+    .sleb128 -4; \
+    .byte   0x11; \
+    AUGMENTATION_PARAM; \
+    .byte   0xc; \
+    .uleb128 0xf; \
+    .uleb128 0x0; \
+    .align 2; \
+ .LECIE1: \
+ .LSFDE1: \
+    .ualong .LEFDE1-.LASFDE1; \
+ .LASFDE1: \
+    .ualong .LASFDE1-.Lframe1; \
+    START_SYMBOL_REF; \
+    .ualong .Lpseudo_end - .Lpseudo_start; \
+    AUGMENTATION_PARAM_FDE; \
+    .byte   0x4; \
+    .ualong .LCFI0-.Lpseudo_start; \
+    .byte   0xe; \
+    .uleb128 0x4; \
+    .byte   0x91; \
+    .uleb128 0x1; \
+    .byte   0x4; \
+    .ualong .LCFI1-.LCFI0; \
+    .byte   0xe; \
+    .uleb128 0x14; \
+    FRAME_REG_##args; \
+    .byte   0x4; \
+    .ualong .LCFI2-.LCFI1; \
+    .byte   0xe; \
+    .uleb128 0x4; \
+    .byte   0x4; \
+    .ualong .LCFI3-.LCFI2; \
+    .byte   0xe; \
+    .uleb128 0x0; \
+    .byte   0xd1; \
+    .byte   0x4; \
+    .ualong .LCFI4-.LCFI3; \
+    .byte   0xe; \
+    .uleb128 0x4; \
+    .byte   0x91; \
+    .uleb128 0x1; \
+    .byte   0x4; \
+    .ualong .LCFI5-.LCFI4; \
+    .byte   0xe; \
+    .uleb128 0x8; \
+    .byte   0x80; \
+    .uleb128 0x2; \
+    .byte   0x4; \
+    .ualong .LCFI6-.LCFI5; \
+    .byte   0xe; \
+    .uleb128 0x4; \
+    .byte   0xc0; \
+    .byte   0x4; \
+    .ualong .LCFI7-.LCFI6; \
+    .byte   0xe; \
+    .uleb128 0x0; \
+    .byte   0xd1; \
+    .align 2; \
+ .LEFDE1: \
+ .previous
+
+# ifdef SHARED
+#  define AUGMENTATION_STRING .string "zR"
+#  define AUGMENTATION_PARAM .uleb128 1; .byte 0x1b
+#  define AUGMENTATION_PARAM_FDE .uleb128 0
+#  define START_SYMBOL_REF .long .Lpseudo_start-.
+# else
+#  define AUGMENTATION_STRING .ascii "\0"
+#  define AUGMENTATION_PARAM
+#  define AUGMENTATION_PARAM_FDE
+#  define START_SYMBOL_REF .long .Lpseudo_start
+# endif
+
+# define FRAME_REG_0	/* Nothing.  */
+# define FRAME_REG_1	FRAME_REG_0; .byte 0x84; .uleb128 5
+# define FRAME_REG_2	FRAME_REG_1; .byte 0x85; .uleb128 4
+# define FRAME_REG_3	FRAME_REG_2; .byte 0x86; .uleb128 3
+# define FRAME_REG_4	FRAME_REG_3; .byte 0x87; .uleb128 2
+# define FRAME_REG_5	FRAME_REG_4
+# define FRAME_REG_6	FRAME_REG_5
 
 # undef PSEUDO_END
 # define PSEUDO_END(sym) \