about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2002-12-12 10:28:11 +0000
committerUlrich Drepper <drepper@redhat.com>2002-12-12 10:28:11 +0000
commit14e7aeceff58b18f970126e1562b0dbf340e2d6c (patch)
treed2f9c7bea22ec0d4d8617a2bd068c9f5ca0a9678
parent688e7bfe2b069ade0353cc41ba1582d12d897714 (diff)
downloadglibc-14e7aeceff58b18f970126e1562b0dbf340e2d6c.tar.gz
glibc-14e7aeceff58b18f970126e1562b0dbf340e2d6c.tar.xz
glibc-14e7aeceff58b18f970126e1562b0dbf340e2d6c.zip
Update.
2002-12-12  Ulrich Drepper  <drepper@redhat.com>

	* sysdeps/unix/sysv/linux/fork-gen.c: Renamed to...
	* sysdeps/unix/sysv/linux/libc_pthread_init.c: ...this.
	Initialize __libc_locking_needed.
	* init.c (__pthread_initialize_minimal): Call __libc_pthread_init
	instead of __register_pthread_fork_handler.
	* sysdeps/pthread/bits/libc-lock.h: Declare __libc_locking_needed.
	* sysdeps/unix/sysv/linux/Makefile (sysdep_routimes): Replace
	fork-gen with libc_pthread_init.
	* sysdeps/unix/sysv/linux/Versions: Use __libc_pthread_init instead
	of __register_pthread_fork_handler.
	* sysdeps/unix/sysv/linux/fork.h: Declare __libc_pthread_init instead
	of __register_pthread_fork_handler.
	* sysdeps/unix/sysv/linux/i386/lowlevellock.h: Use
	__libc_locking_needed to determine whether lock prefix can be avoided.
	* sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Likewise.
-rw-r--r--nptl/ChangeLog18
-rw-r--r--nptl/init.c2
-rw-r--r--nptl/sysdeps/pthread/bits/libc-lock.h4
-rw-r--r--nptl/sysdeps/unix/sysv/linux/Makefile2
-rw-r--r--nptl/sysdeps/unix/sysv/linux/Versions2
-rw-r--r--nptl/sysdeps/unix/sysv/linux/fork.h4
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S185
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h60
-rw-r--r--nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c (renamed from nptl/sysdeps/unix/sysv/linux/fork-gen.c)12
9 files changed, 279 insertions, 10 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index c2a0347dd3..245fa94bd9 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,21 @@
+2002-12-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/fork-gen.c: Renamed to...
+	* sysdeps/unix/sysv/linux/libc_pthread_init.c: ...this.
+	Initialize __libc_locking_needed.
+	* init.c (__pthread_initialize_minimal): Call __libc_pthread_init
+	instead of __register_pthread_fork_handler.
+	* sysdeps/pthread/bits/libc-lock.h: Declare __libc_locking_needed.
+	* sysdeps/unix/sysv/linux/Makefile (sysdep_routimes): Replace
+	fork-gen with libc_pthread_init.
+	* sysdeps/unix/sysv/linux/Versions: Use __libc_pthread_init instead
+	of __register_pthread_fork_handler.
+	* sysdeps/unix/sysv/linux/fork.h: Declare __libc_pthread_init instead
+	of __register_pthread_fork_handler.
+	* sysdeps/unix/sysv/linux/i386/lowlevellock.h: Use
+	__libc_locking_needed to determine whether lock prefix can be avoided.
+	* sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Likewise.
+
 2002-12-11  Ulrich Drepper  <drepper@redhat.com>
 
 	* Makefile (tests): Add tst-cleanup1.
diff --git a/nptl/init.c b/nptl/init.c
index 678c0a56c8..7686e8ca29 100644
--- a/nptl/init.c
+++ b/nptl/init.c
@@ -167,5 +167,5 @@ __pthread_initialize_minimal (void)
   __static_tls_size = roundup (__static_tls_size, __static_tls_align);
 
   /* Register the fork generation counter with the libc.  */
-  __register_pthread_fork_handler (&__fork_generation, __reclaim_stacks);
+  __libc_pthread_init (&__fork_generation, __reclaim_stacks);
 }
diff --git a/nptl/sysdeps/pthread/bits/libc-lock.h b/nptl/sysdeps/pthread/bits/libc-lock.h
index de2ec7bb25..e594ede1dd 100644
--- a/nptl/sysdeps/pthread/bits/libc-lock.h
+++ b/nptl/sysdeps/pthread/bits/libc-lock.h
@@ -25,6 +25,10 @@
 #include <stddef.h>
 
 
+/* Nonzero if locking is needed.  */
+extern int __libc_locking_needed attribute_hidden;
+
+
 /* Fortunately Linux now has a mean to do locking which is realtime
    safe without the aid of the thread library.  We also need no fancy
    options like error checking mutexes etc.  We only need simple
diff --git a/nptl/sysdeps/unix/sysv/linux/Makefile b/nptl/sysdeps/unix/sysv/linux/Makefile
index 9a84534d5b..c079a4013d 100644
--- a/nptl/sysdeps/unix/sysv/linux/Makefile
+++ b/nptl/sysdeps/unix/sysv/linux/Makefile
@@ -18,7 +18,7 @@
 # 02111-1307 USA.  */
 
 ifeq ($(subdir),nptl)
-sysdep_routines += register-atfork unregister-atfork fork-gen
+sysdep_routines += register-atfork unregister-atfork libc_pthread_init
 
 libpthread-sysdep_routines += pt-fork
 endif
diff --git a/nptl/sysdeps/unix/sysv/linux/Versions b/nptl/sysdeps/unix/sysv/linux/Versions
index 117598c95f..8fea097e43 100644
--- a/nptl/sysdeps/unix/sysv/linux/Versions
+++ b/nptl/sysdeps/unix/sysv/linux/Versions
@@ -1,6 +1,6 @@
 libc {
   GLIBC_PRIVATE {
-    __register_atfork; __register_pthread_fork_handler;
+    __register_atfork; __libc_pthread_init;
     __libc_current_sigrtmin_private; __libc_current_sigrtmax_private;
     __libc_allocate_rtsig_private;
   }
diff --git a/nptl/sysdeps/unix/sysv/linux/fork.h b/nptl/sysdeps/unix/sysv/linux/fork.h
index 85722a59eb..0bc283d1bc 100644
--- a/nptl/sysdeps/unix/sysv/linux/fork.h
+++ b/nptl/sysdeps/unix/sysv/linux/fork.h
@@ -56,5 +56,5 @@ extern int __register_atfork (void (*__prepare) (void),
 			      void *dso_handle);
 
 /* Register the generation counter in the libpthread with the libc.  */
-extern void __register_pthread_fork_handler (unsigned long int *__ptr,
-					     void (*reclaim) (void));
+extern void __libc_pthread_int (unsigned long int *__ptr,
+				void (*reclaim) (void));
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S
index 3ce1d6fe72..9a124ab0c2 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S
@@ -1 +1,184 @@
-#include "lowlevellock.S"
+/* 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 <sysdep.h>
+
+	.text
+
+#define SYS_gettimeofday	__NR_gettimeofday
+#define SYS_futex		240
+#define FUTEX_WAIT		0
+#define FUTEX_WAKE		1
+
+#define ETIMEDOUT               110
+
+
+	.globl	__lll_lock_wait
+	.type	__lll_lock_wait,@function
+	.hidden	__lll_lock_wait
+	.align	16
+__lll_lock_wait:
+	pushl	%esi
+	pushl	%ebx
+	pushl	%edx
+
+	movl	%ecx, %ebx
+	xorl	%esi, %esi	/* No timeout.  */
+	xorl	%ecx, %ecx	/* movl $FUTEX_WAIT, %ecx */
+1:
+	leal	-1(%eax), %edx	/* account for the preceeded xadd.  */
+	movl	$SYS_futex, %eax
+	int	$0x80
+
+	orl	$-1, %eax	/* Load -1.  */
+#ifndef UP
+	cmpl	$0, __libc_locking_needed
+	je,pt	0f
+	lock
+0:
+#endif
+	xaddl	%eax, (%ebx)
+	jne	1b
+
+	movl	$-1, (%ebx)
+
+	popl	%edx
+	popl	%ebx
+	popl	%esi
+	ret
+	.size	__lll_lock_wait,.-__lll_lock_wait
+
+
+	.globl	lll_unlock_wake_cb
+	.type	lll_unlock_wake_cb,@function
+	.hidden	lll_unlock_wake_cb
+	.align	16
+lll_unlock_wake_cb:
+	pushl	%esi
+	pushl	%ebx
+	pushl	%ecx
+	pushl	%edx
+
+	movl	20(%esp), %ebx
+#ifndef UP
+	cmpl	$0, __libc_locking_needed
+	je,pt	0f
+	lock
+0:
+#endif
+	incl	(%ebx)
+	jng	1f
+
+	popl	%edx
+	popl	%ecx
+	popl	%ebx
+	popl	%esi
+	ret
+	.size	lll_unlock_wake_cb,.-lll_unlock_wake_cb
+
+
+	.globl	__lll_unlock_wake
+	.type	__lll_unlock_wake,@function
+	.hidden	__lll_unlock_wake
+__lll_unlock_wake:
+	pushl	%esi
+	pushl	%ebx
+	pushl	%ecx
+	pushl	%edx
+
+	movl	%eax, %ebx
+1:	movl	$FUTEX_WAKE, %ecx
+	movl	$1, %edx	/* Wake one thread.  */
+	xorl	%esi, %esi
+	movl	%edx, (%ebx)	/* Stores '$1'.  */
+	movl	$SYS_futex, %eax
+	int	$0x80
+
+	popl	%edx
+	popl	%ecx
+	popl	%ebx
+	popl	%esi
+	ret
+	.size	__lll_unlock_wake,.-__lll_unlock_wake
+
+
+	.globl	__lll_timedwait_tid
+	.type	__lll_timedwait_tid,@function
+	.hidden	__lll_timedwait_tid
+__lll_timedwait_tid:
+	pushl	%edi
+	pushl	%esi
+	pushl	%ebx
+	pushl	%ebp
+
+	movl	%eax, %ebp
+	movl	%edx, %edi
+	subl	$8, %esp
+
+	/* Get current time.  */
+2:	movl	%esp, %ebx
+	xorl	%ecx, %ecx
+	movl	$SYS_gettimeofday, %eax
+	int	$0x80
+
+	/* Compute relative timeout.  */
+	movl	4(%esp), %eax
+	movl	$1000, %edx
+	mul	%edx		/* Milli seconds to nano seconds.  */
+	movl	(%edi), %ecx
+	movl	4(%edi), %edx
+	subl	(%esp), %ecx
+	subl	%eax, %edx
+	jns	5f
+	addl	$1000000000, %edx
+	decl	%ecx
+5:	testl	%ecx, %ecx
+	js	6f		/* Time is already up.  */
+
+	movl	%ecx, (%esp)	/* Store relative timeout.  */
+	movl	%edx, 4(%esp)
+
+	movl	(%ebp), %edx
+	testl	%edx, %edx
+	jz	4f
+
+	movl	%esp, %esi
+	xorl	%ecx, %ecx	/* movl $FUTEX_WAIT, %ecx */
+	movl	%ebp, %ebx
+	movl	$SYS_futex, %eax
+	int	$0x80
+
+	movl	%eax, %edx
+
+	cmpl	$0, (%ebx)
+	jne	1f
+4:	xorl	%eax, %eax
+
+3:	addl	$8, %esp
+	popl	%ebp
+	popl	%ebx
+	popl	%esi
+	popl	%edi
+	ret
+
+1:	cmpl	$-ETIMEDOUT, %edx
+	jne	2b
+6:	movl	$ETIMEDOUT, %eax
+	jmp	3b
+	.size	__lll_timedwait_tid,.-__lll_timedwait_tid
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h
index a3c02498f4..470dcf6108 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h
+++ b/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h
@@ -139,7 +139,8 @@ extern int lll_unlock_wake_cb (int *__futex) attribute_hidden;
    <0  -  taken by more users */
 
 
-#define lll_trylock(futex) \
+#if defined NOT_IN_libc || defined UP
+# define lll_trylock(futex) \
   ({ unsigned char ret;							      \
      __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1; setne %0"		      \
 		       : "=a" (ret), "=m" (futex)			      \
@@ -148,7 +149,7 @@ extern int lll_unlock_wake_cb (int *__futex) attribute_hidden;
      ret; })
 
 
-#define lll_lock(futex) \
+# define lll_lock(futex) \
   (void) ({ int ignore1, ignore2;					      \
 	    __asm __volatile (LOCK_INSTR "xaddl %0, %2\n\t"		      \
 			      "jne 1f\n\t"				      \
@@ -163,7 +164,7 @@ extern int lll_unlock_wake_cb (int *__futex) attribute_hidden;
 			      : "memory"); })
 
 
-#define lll_unlock(futex) \
+# define lll_unlock(futex) \
   (void) ({ int ignore;							      \
             __asm __volatile (LOCK_INSTR "incl %0\n\t"			      \
 			      "jng 1f\n\t"				      \
@@ -176,6 +177,59 @@ extern int lll_unlock_wake_cb (int *__futex) attribute_hidden;
 			      : "=m" (futex), "=&a" (ignore)		      \
 			      : "0" (futex)				      \
 			      : "memory"); })
+#else
+/* Special versions of the macros for use in libc itself.  They avoid
+   the lock prefix when the thread library is not used.
+
+   XXX In future we might even want to avoid it on UP machines.  */
+
+# define lll_trylock(futex) \
+  ({ unsigned char ret;							      \
+     __asm __volatile ("cmpl $0, __libc_locking_needed\n\t"		      \
+		       "je,pt 0f\n\t"					      \
+		       "lock\n"						      \
+		       "0:\tcmpxchgl %2, %1; setne %0"			      \
+		       : "=a" (ret), "=m" (futex)			      \
+		       : "r" (0), "1" (futex), "0" (1)			      \
+		       : "memory");					      \
+     ret; })
+
+
+# define lll_lock(futex) \
+  (void) ({ int ignore1, ignore2;					      \
+	    __asm __volatile ("cmpl $0, __libc_locking_needed\n\t"	      \
+			      "je,pt 0f\n\t"				      \
+			      "lock\n"					      \
+			      "0:\txaddl %0, %2\n\t"			      \
+			      "jne 1f\n\t"				      \
+			      ".subsection 1\n"				      \
+			      "1:\tleal %2, %%ecx\n\t"			      \
+			      "call __lll_lock_wait\n\t"		      \
+			      "jmp 2f\n\t"				      \
+			      ".previous\n"				      \
+			      "2:"					      \
+			      : "=a" (ignore1), "=&c" (ignore2), "=m" (futex) \
+			      : "0" (-1), "2" (futex)			      \
+			      : "memory"); })
+
+
+# define lll_unlock(futex) \
+  (void) ({ int ignore;							      \
+            __asm __volatile ("cmpl $0, __libc_locking_needed\n\t"	      \
+			      "je,pt 0f\n\t"				      \
+			      "lock\n"					      \
+			      "0:\tincl %0\n\t"				      \
+			      "jng 1f\n\t"				      \
+			      ".subsection 1\n"				      \
+			      "1:\tleal %0, %%eax\n\t"			      \
+			      "call __lll_unlock_wake\n\t"		      \
+			      "jmp 2f\n\t"				      \
+			      ".previous\n"				      \
+			      "2:"					      \
+			      : "=m" (futex), "=&a" (ignore)		      \
+			      : "0" (futex)				      \
+			      : "memory"); })
+#endif
 
 
 #define lll_islocked(futex) \
diff --git a/nptl/sysdeps/unix/sysv/linux/fork-gen.c b/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c
index ff00261404..d7f1c03b5e 100644
--- a/nptl/sysdeps/unix/sysv/linux/fork-gen.c
+++ b/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c
@@ -19,19 +19,29 @@
 
 #include <list.h>
 #include "fork.h"
+#include <bits/libc-lock.h>
 
 
 static struct fork_handler pthread_child_handler;
 
+/* Global variable signalled when locking is needed.  */
+int __libc_locking_needed;
+
 
 void
-__register_pthread_fork_handler (ptr, reclaim)
+__libc_pthread_init (ptr, reclaim)
      unsigned long int *ptr;
      void (*reclaim) (void);
 {
+  /* Remember the pointer to the generation counter in libpthread.  */
   __fork_generation_pointer = ptr;
 
+  /* Called by a child after fork.  */
   pthread_child_handler.handler = reclaim;
 
+  /* The fork handler needed by libpthread.  */
   list_add_tail (&pthread_child_handler.list, &__fork_child_list);
+
+  /* Signal the internal locking code that locking is needed now.  */
+  __libc_locking_needed = 1;
 }