summaryrefslogtreecommitdiff
path: root/nptl/sysdeps/unix/sysv/linux/i386
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2006-02-17 16:15:56 +0000
committerJakub Jelinek <jakub@redhat.com>2006-02-17 16:15:56 +0000
commit9c09cd93597a91d6b0b59c8813be97d530e7551c (patch)
treecd7ea8e6dc157e92ffd5f20dfa997e8be5b7da8b /nptl/sysdeps/unix/sysv/linux/i386
parent7d8db4cd587349f485fb85f4bea9e3011a3e55d7 (diff)
Updated to fedora-glibc-20060217T1609
Diffstat (limited to 'nptl/sysdeps/unix/sysv/linux/i386')
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S186
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrobustlock.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrobustlock.S20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h118
4 files changed, 343 insertions, 1 deletions
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S
new file mode 100644
index 0000000000..1c516c7424
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S
@@ -0,0 +1,186 @@
+/* Copyright (C) 2002, 2003, 2004, 2006 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>
+#include <pthread-errnos.h>
+#include <lowlevelrobustlock.h>
+
+ .text
+
+#ifndef LOCK
+# ifdef UP
+# define LOCK
+# else
+# define LOCK lock
+# endif
+#endif
+
+#define SYS_gettimeofday __NR_gettimeofday
+#define SYS_futex 240
+#define FUTEX_WAIT 0
+#define FUTEX_WAKE 1
+#define FUTEX_WAITERS 0x80000000
+#define FUTEX_OWNER_DIED 0x40000000
+
+
+ .globl __lll_robust_mutex_lock_wait
+ .type __lll_robust_mutex_lock_wait,@function
+ .hidden __lll_robust_mutex_lock_wait
+ .align 16
+__lll_robust_mutex_lock_wait:
+ pushl %edx
+ pushl %ebx
+ pushl %esi
+
+ movl %ecx, %ebx
+ xorl %esi, %esi /* No timeout. */
+ xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
+
+4: movl %eax, %edx
+ orl $FUTEX_WAITERS, %edx
+
+ testl $FUTEX_OWNER_DIED, %eax
+ jnz 3f
+
+ cmpl %edx, %eax /* NB: %edx == 2 */
+ je 1f
+
+ LOCK
+ cmpxchgl %edx, (%ebx)
+ jnz 2f
+
+1: movl $SYS_futex, %eax
+ ENTER_KERNEL
+
+ movl (%ebx), %eax
+
+2: test %eax, %eax
+ jne 4b
+
+ movl %gs:TID, %edx
+ LOCK
+ cmpxchgl %edx, (%ebx)
+ jnz 4b
+ /* NB: %eax == 0 */
+
+3: popl %esi
+ popl %ebx
+ popl %edx
+ ret
+ .size __lll_robust_mutex_lock_wait,.-__lll_robust_mutex_lock_wait
+
+
+ .globl __lll_robust_mutex_timedlock_wait
+ .type __lll_robust_mutex_timedlock_wait,@function
+ .hidden __lll_robust_mutex_timedlock_wait
+ .align 16
+__lll_robust_mutex_timedlock_wait:
+ /* Check for a valid timeout value. */
+ cmpl $1000000000, 4(%edx)
+ jae 3f
+
+ pushl %edi
+ pushl %esi
+ pushl %ebx
+ pushl %ebp
+
+ /* Stack frame for the timespec and timeval structs. */
+ subl $12, %esp
+
+ movl %ecx, %ebp
+ movl %edx, %edi
+
+1: movl %eax, 8(%esp)
+
+ /* Get current time. */
+ movl %esp, %ebx
+ xorl %ecx, %ecx
+ movl $SYS_gettimeofday, %eax
+ ENTER_KERNEL
+
+ /* 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 4f
+ addl $1000000000, %edx
+ subl $1, %ecx
+4: testl %ecx, %ecx
+ js 8f /* Time is already up. */
+
+ /* Store relative timeout. */
+ movl %ecx, (%esp)
+ movl %edx, 4(%esp)
+
+ movl %ebp, %ebx
+
+ movl 8(%esp), %edx
+ movl %edx, %eax
+ orl $FUTEX_WAITERS, %edx
+
+ testl $FUTEX_OWNER_DIED, %eax
+ jnz 6f
+
+ cmpl %eax, %edx
+ je 2f
+
+ LOCK
+ cmpxchgl %edx, (%ebx)
+ movl $0, %ecx /* Must use mov to avoid changing cc. */
+ jnz 5f
+
+2:
+ /* Futex call. */
+ movl %esp, %esi
+ xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
+ movl $SYS_futex, %eax
+ ENTER_KERNEL
+ movl %eax, %ecx
+
+ movl (%ebx), %eax
+
+5: testl %eax, %eax
+ jne 7f
+
+ movl %gs:TID, %edx
+ LOCK
+ cmpxchgl %edx, (%ebx)
+ jnz 7f
+
+6: addl $12, %esp
+ popl %ebp
+ popl %ebx
+ popl %esi
+ popl %edi
+ ret
+
+ /* Check whether the time expired. */
+7: cmpl $-ETIMEDOUT, %ecx
+ jne 1b
+
+8: movl $ETIMEDOUT, %eax
+ jmp 6b
+
+3: movl $EINVAL, %eax
+ ret
+ .size __lll_robust_mutex_timedlock_wait,.-__lll_robust_mutex_timedlock_wait
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrobustlock.S b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrobustlock.S
new file mode 100644
index 0000000000..f768e16a7d
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrobustlock.S
@@ -0,0 +1,20 @@
+/* Copyright (C) 2002, 2006 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 "../i486/lowlevelrobustlock.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrobustlock.S b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrobustlock.S
new file mode 100644
index 0000000000..f768e16a7d
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrobustlock.S
@@ -0,0 +1,20 @@
+/* Copyright (C) 2002, 2006 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 "../i486/lowlevelrobustlock.S"
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h
index b233d9747f..afdba009a0 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h
+++ b/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h
@@ -139,6 +139,16 @@ extern int __lll_mutex_unlock_wake (int *__futex)
ret; })
+#define lll_robust_mutex_trylock(futex, id) \
+ ({ int ret; \
+ __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1" \
+ : "=a" (ret), "=m" (futex) \
+ : "r" (id), "m" (futex), \
+ "0" (LLL_MUTEX_LOCK_INITIALIZER) \
+ : "memory"); \
+ ret; })
+
+
#define lll_mutex_cond_trylock(futex) \
({ int ret; \
__asm __volatile (LOCK_INSTR "cmpxchgl %2, %1" \
@@ -167,6 +177,25 @@ extern int __lll_mutex_unlock_wake (int *__futex)
: "memory"); })
+#define lll_robust_mutex_lock(futex, id) \
+ ({ int result, ignore; \
+ __asm __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t" \
+ "jnz _L_mutex_lock_%=\n\t" \
+ ".subsection 1\n\t" \
+ ".type _L_mutex_lock_%=,@function\n" \
+ "_L_mutex_lock_%=:\n\t" \
+ "leal %2, %%ecx\n\t" \
+ "call __lll_robust_mutex_lock_wait\n\t" \
+ "jmp 1f\n\t" \
+ ".size _L_mutex_lock_%=,.-_L_mutex_lock_%=\n" \
+ ".previous\n" \
+ "1:" \
+ : "=a" (result), "=c" (ignore), "=m" (futex) \
+ : "0" (0), "1" (id), "m" (futex) \
+ : "memory"); \
+ result; })
+
+
/* Special version of lll_mutex_lock which causes the unlock function to
always wakeup waiters. */
#define lll_mutex_cond_lock(futex) \
@@ -187,6 +216,25 @@ extern int __lll_mutex_unlock_wake (int *__futex)
: "memory"); })
+#define lll_robust_mutex_cond_lock(futex, id) \
+ ({ int result, ignore; \
+ __asm __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t" \
+ "jnz _L_mutex_cond_lock_%=\n\t" \
+ ".subsection 1\n\t" \
+ ".type _L_mutex_cond_lock_%=,@function\n" \
+ "_L_mutex_cond_lock_%=:\n\t" \
+ "leal %2, %%ecx\n\t" \
+ "call __lll_robust_mutex_lock_wait\n\t" \
+ "jmp 1f\n\t" \
+ ".size _L_mutex_cond_lock_%=,.-_L_mutex_cond_lock_%=\n"\
+ ".previous\n" \
+ "1:" \
+ : "=a" (result), "=c" (ignore), "=m" (futex) \
+ : "0" (0), "1" (id | FUTEX_WAITERS), "m" (futex) \
+ : "memory"); \
+ result; })
+
+
#define lll_mutex_timedlock(futex, timeout) \
({ int result, ignore1, ignore2; \
__asm __volatile (LOCK_INSTR "cmpxchgl %1, %3\n\t" \
@@ -208,9 +256,30 @@ extern int __lll_mutex_unlock_wake (int *__futex)
result; })
+#define lll_robust_mutex_timedlock(futex, timeout, id) \
+ ({ int result, ignore1, ignore2; \
+ __asm __volatile (LOCK_INSTR "cmpxchgl %1, %3\n\t" \
+ "jnz _L_mutex_timedlock_%=\n\t" \
+ ".subsection 1\n\t" \
+ ".type _L_mutex_timedlock_%=,@function\n" \
+ "_L_mutex_timedlock_%=:\n\t" \
+ "leal %3, %%ecx\n\t" \
+ "movl %7, %%edx\n\t" \
+ "call __lll_robust_mutex_timedlock_wait\n\t" \
+ "jmp 1f\n\t" \
+ ".size _L_mutex_timedlock_%=,.-_L_mutex_timedlock_%=\n"\
+ ".previous\n" \
+ "1:" \
+ : "=a" (result), "=c" (ignore1), "=&d" (ignore2), \
+ "=m" (futex) \
+ : "0" (0), "1" (id), "m" (futex), "m" (timeout) \
+ : "memory"); \
+ result; })
+
+
#define lll_mutex_unlock(futex) \
(void) ({ int ignore; \
- __asm __volatile (LOCK_INSTR "subl $1,%0\n\t" \
+ __asm __volatile (LOCK_INSTR "subl $1, %0\n\t" \
"jne _L_mutex_unlock_%=\n\t" \
".subsection 1\n\t" \
".type _L_mutex_unlock_%=,@function\n" \
@@ -226,6 +295,53 @@ extern int __lll_mutex_unlock_wake (int *__futex)
: "memory"); })
+#define lll_robust_mutex_unlock(futex) \
+ (void) ({ int ignore; \
+ __asm __volatile (LOCK_INSTR "andl %2, %0\n\t" \
+ "jne _L_mutex_unlock_%=\n\t" \
+ ".subsection 1\n\t" \
+ ".type _L_mutex_unlock_%=,@function\n" \
+ "_L_mutex_unlock_%=:\n\t" \
+ "leal %0, %%eax\n\t" \
+ "call __lll_mutex_unlock_wake\n\t" \
+ "jmp 1f\n\t" \
+ ".size _L_mutex_unlock_%=,.-_L_mutex_unlock_%=\n" \
+ ".previous\n" \
+ "1:" \
+ : "=m" (futex), "=&a" (ignore) \
+ : "i" (FUTEX_WAITERS), "m" (futex) \
+ : "memory"); })
+
+
+#define lll_robust_mutex_dead(futex) \
+ (void) ({ int __ignore; \
+ register int _nr asm ("edx") = 1; \
+ __asm __volatile (LOCK_INSTR "orl %5, (%2)\n\t" \
+ LLL_EBX_LOAD \
+ LLL_ENTER_KERNEL \
+ LLL_EBX_LOAD \
+ : "=a" (__ignore) \
+ : "0" (SYS_futex), LLL_EBX_REG (&(futex)), \
+ "c" (FUTEX_WAKE), "d" (_nr), \
+ "i" (FUTEX_OWNER_DIED), \
+ "i" (offsetof (tcbhead_t, sysinfo))); })
+
+
+#define lll_futex_wake(futex, nr) \
+ do { \
+ int __ignore; \
+ register __typeof (nr) _nr asm ("edx") = (nr); \
+ __asm __volatile (LLL_EBX_LOAD \
+ LLL_ENTER_KERNEL \
+ LLL_EBX_LOAD \
+ : "=a" (__ignore) \
+ : "0" (SYS_futex), LLL_EBX_REG (futex), \
+ "c" (FUTEX_WAKE), "d" (_nr), \
+ "i" (0) /* phony, to align next arg's number */, \
+ "i" (offsetof (tcbhead_t, sysinfo))); \
+ } while (0)
+
+
#define lll_mutex_islocked(futex) \
(futex != 0)