aboutsummaryrefslogtreecommitdiff
path: root/nptl/sysdeps/unix
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 /nptl/sysdeps/unix
parent688e7bfe2b069ade0353cc41ba1582d12d897714 (diff)
downloadglibc-14e7aeceff58b18f970126e1562b0dbf340e2d6c.tar
glibc-14e7aeceff58b18f970126e1562b0dbf340e2d6c.tar.gz
glibc-14e7aeceff58b18f970126e1562b0dbf340e2d6c.tar.bz2
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.
Diffstat (limited to 'nptl/sysdeps/unix')
-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
6 files changed, 256 insertions, 9 deletions
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;
}