aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2007-05-23 08:33:06 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2007-05-23 08:33:06 +0000
commit1c182de9a99afd152c548bda64ab626a1b9f5a3e (patch)
tree9e0211f55a99ffc4fef4f84e9c3b74e63cc9cbc6 /sys
parentd75d56060e0bb6ae2d9b44e26fb050c6fd82c299 (diff)
downloadsrc-1c182de9a99afd152c548bda64ab626a1b9f5a3e.tar.gz
src-1c182de9a99afd152c548bda64ab626a1b9f5a3e.zip
Move futex support code from <arch>/support.s into linux compat directory.
Implement all futex atomic operations in assembler to not depend on the fuword() that does not allow to distinguish between -1 and failure return. Correctly return 0 from atomic operations on success. In collaboration with: rdivacky Tested by: Scot Hetzel <swhetzel gmail com>, Milos Vyletel <mvyletel mzm cz> Sponsored by: Google SoC 2007
Notes
Notes: svn path=/head/; revision=169895
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/support.S43
-rw-r--r--sys/amd64/linux32/linux32_support.s124
-rw-r--r--sys/compat/linux/linux_futex.c113
-rw-r--r--sys/conf/files.amd643
-rw-r--r--sys/conf/files.i3861
-rw-r--r--sys/conf/files.pc981
-rw-r--r--sys/i386/i386/support.s45
-rw-r--r--sys/i386/linux/linux_support.s127
-rw-r--r--sys/modules/linux/Makefile12
9 files changed, 303 insertions, 166 deletions
diff --git a/sys/amd64/amd64/support.S b/sys/amd64/amd64/support.S
index c828877a2fbc..782cde9ec6e4 100644
--- a/sys/amd64/amd64/support.S
+++ b/sys/amd64/amd64/support.S
@@ -671,49 +671,6 @@ ENTRY(longjmp)
incl %eax
ret
-/*****************************************************************************/
-/* linux_futex support */
-/*****************************************************************************/
-
-futex_fault:
- movq $0,PCB_ONFAULT(%rcx)
- movq $-EFAULT,%rax
- ret
-
-ENTRY(futex_xchgl)
- movq PCPU(CURPCB),%rcx
- movq $futex_fault,PCB_ONFAULT(%rcx)
-
- movq $VM_MAXUSER_ADDRESS-4,%rax
- cmpq %rax,%rsi
- ja futex_fault
-
-#ifdef SMP
- lock
-#endif
- xchgl %edi,(%rsi)
- movl %edi,(%rdx)
- xorl %eax,%eax
- movq %rax,PCB_ONFAULT(%rcx)
- ret
-
-ENTRY(futex_addl)
- movq PCPU(CURPCB),%rcx
- movq $futex_fault,PCB_ONFAULT(%rcx)
-
- movq $VM_MAXUSER_ADDRESS-4,%rax
- cmpq %rax,%rsi
- ja futex_fault
-
-#ifdef SMP
- lock
-#endif
- xaddl %edi,(%rsi)
- movl %edi,(%rdx)
- xorl %eax,%eax
- movq %rax,PCB_ONFAULT(%rcx)
- ret
-
/*
* Support for BB-profiling (gcc -a). The kernbb program will extract
* the data from the kernel.
diff --git a/sys/amd64/linux32/linux32_support.s b/sys/amd64/linux32/linux32_support.s
new file mode 100644
index 000000000000..42375c3f9bff
--- /dev/null
+++ b/sys/amd64/linux32/linux32_support.s
@@ -0,0 +1,124 @@
+/*-
+ * Copyright (c) 2007 Konstantin Belousov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "linux32_assym.h" /* system definitions */
+#include <machine/asmacros.h> /* miscellaneous asm macros */
+
+#include "assym.s"
+
+futex_fault:
+ movq $0,PCB_ONFAULT(%r8)
+ movl $-EFAULT,%eax
+ ret
+
+ENTRY(futex_xchgl)
+ movq PCPU(CURPCB),%r8
+ movq $futex_fault,PCB_ONFAULT(%r8)
+ movq $VM_MAXUSER_ADDRESS-4,%rax
+ cmpq %rax,%rsi
+ ja futex_fault
+ xchgl %edi,(%rsi)
+ movl %edi,(%rdx)
+ xorl %eax,%eax
+ movq %rax,PCB_ONFAULT(%r8)
+ ret
+
+ENTRY(futex_addl)
+ movq PCPU(CURPCB),%r8
+ movq $futex_fault,PCB_ONFAULT(%r8)
+ movq $VM_MAXUSER_ADDRESS-4,%rax
+ cmpq %rax,%rsi
+ ja futex_fault
+#ifdef SMP
+ lock
+#endif
+ xaddl %edi,(%rsi)
+ movl %edi,(%rdx)
+ xorl %eax,%eax
+ movq %rax,PCB_ONFAULT(%r8)
+ ret
+
+ENTRY(futex_orl)
+ movq PCPU(CURPCB),%r8
+ movq $futex_fault,PCB_ONFAULT(%r8)
+ movq $VM_MAXUSER_ADDRESS-4,%rax
+ cmpq %rax,%rsi
+ ja futex_fault
+ movl (%rsi),%eax
+1: movl %eax,%ecx
+ orl %edi,%ecx
+#ifdef SMP
+ lock
+#endif
+ cmpxchgl %ecx,(%rsi)
+ jnz 1b
+ movl %eax,(%rdx)
+ xorl %eax,%eax
+ movq %rax,PCB_ONFAULT(%r8)
+ ret
+
+ENTRY(futex_andl)
+ movq PCPU(CURPCB),%r8
+ movq $futex_fault,PCB_ONFAULT(%r8)
+ movq $VM_MAXUSER_ADDRESS-4,%rax
+ cmpq %rax,%rsi
+ ja futex_fault
+ movl (%rsi),%eax
+1: movl %eax,%ecx
+ andl %edi,%ecx
+#ifdef SMP
+ lock
+#endif
+ cmpxchgl %ecx,(%rsi)
+ jnz 1b
+ movl %eax,(%rdx)
+ xorl %eax,%eax
+ movq %rax,PCB_ONFAULT(%r8)
+ ret
+
+ENTRY(futex_xorl)
+ movq PCPU(CURPCB),%r8
+ movq $futex_fault,PCB_ONFAULT(%r8)
+ movq $VM_MAXUSER_ADDRESS-4,%rax
+ cmpq %rax,%rsi
+ ja futex_fault
+ movl (%rsi),%eax
+1: movl %eax,%ecx
+ xorl %edi,%ecx
+#ifdef SMP
+ lock
+#endif
+ cmpxchgl %ecx,(%rsi)
+ jnz 1b
+ movl %eax,(%rdx)
+ xorl %eax,%eax
+ movq %rax,PCB_ONFAULT(%r8)
+ ret
diff --git a/sys/compat/linux/linux_futex.c b/sys/compat/linux/linux_futex.c
index f3fe997c3b8e..be719b8dbad2 100644
--- a/sys/compat/linux/linux_futex.c
+++ b/sys/compat/linux/linux_futex.c
@@ -90,13 +90,13 @@ static void futex_put(struct futex *);
static int futex_sleep(struct futex *, struct thread *, unsigned long);
static int futex_wake(struct futex *, int, struct futex *, int);
static int futex_atomic_op(struct thread *td, int encoded_op, caddr_t uaddr);
-static int futex_orl(int oparg, caddr_t uaddr, int *oldval);
-static int futex_andl(int oparg, caddr_t uaddr, int *oldval);
-static int futex_xorl(int oparg, caddr_t uaddr, int *oldval);
/* support.s */
int futex_xchgl(int oparg, caddr_t uaddr, int *oldval);
int futex_addl(int oparg, caddr_t uaddr, int *oldval);
+int futex_orl(int oparg, caddr_t uaddr, int *oldval);
+int futex_andl(int oparg, caddr_t uaddr, int *oldval);
+int futex_xorl(int oparg, caddr_t uaddr, int *oldval);
int
linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
@@ -114,8 +114,8 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
#ifdef DEBUG
if (ldebug(sys_futex))
- printf(ARGS(futex, "%p, %i, %i"), args->uaddr, args->op,
- args->val);
+ printf(ARGS(futex, "%p, %i, %i, *, %p, %i"), args->uaddr, args->op,
+ args->val, args->uaddr2, args->val3);
#endif
switch (args->op) {
@@ -274,7 +274,7 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
#ifdef DEBUG
if (ldebug(sys_futex))
printf("FUTEX_WAKE_OP: %d: uaddr = %p, op = %d, "
- "val = %d, uaddr2 = %p, val3 = %d\n",
+ "val = %x, uaddr2 = %p, val3 = %x\n",
td->td_proc->p_pid, args->uaddr, args->op,
args->val, args->uaddr2, args->val3);
#endif
@@ -286,8 +286,11 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
* negative as errors
*/
op_ret = futex_atomic_op(td, args->val3, args->uaddr2);
+#ifdef DEBUG
+ if (ldebug(sys_futex))
+ printf("futex_atomic_op ret %d\n", op_ret);
+#endif
if (op_ret < 0) {
-
/* XXX: We don't handle the EFAULT yet. */
if (op_ret != -EFAULT) {
futex_put(f);
@@ -301,7 +304,6 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
FUTEX_SYSTEM_UNLOCK;
return (EFAULT);
-
}
ret = futex_wake(f, args->val, NULL, 0);
@@ -327,7 +329,7 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
args->op);
break;
}
- return 0;
+ return (0);
}
static struct futex *
@@ -401,9 +403,12 @@ futex_sleep(struct futex *f, struct thread *td, unsigned long timeout)
TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list);
FUTEX_UNLOCK;
+ /* if we got woken up in futex_wake */
if ((ret == 0) && (wp->wp_new_futex != NULL)) {
+ /* suspend us on the new futex */
ret = futex_sleep(wp->wp_new_futex, td, timeout);
- futex_put(wp->wp_new_futex); /* futex_get called in wakeup */
+ /* and release the old one */
+ futex_put(wp->wp_new_futex);
}
free(wp, M_LINUX);
@@ -458,8 +463,10 @@ futex_atomic_op(struct thread *td, int encoded_op, caddr_t uaddr)
oparg = 1 << oparg;
#ifdef DEBUG
- printf("futex_atomic_op: op = %d, cmp = %d, oparg = %d, cmparg = %d, "
- "uaddr = %p\n", op, cmp, oparg, cmparg, uaddr);
+ if (ldebug(sys_futex))
+ printf("futex_atomic_op: op = %d, cmp = %d, oparg = %x, "
+ "cmparg = %x, uaddr = %p\n",
+ op, cmp, oparg, cmparg, uaddr);
#endif
/* XXX: linux verifies access here and returns EFAULT */
@@ -481,70 +488,26 @@ futex_atomic_op(struct thread *td, int encoded_op, caddr_t uaddr)
break;
default:
ret = -ENOSYS;
+ break;
}
- if (!ret)
- switch (cmp) {
- case FUTEX_OP_CMP_EQ:
- ret = (oldval == cmparg);
- break;
- case FUTEX_OP_CMP_NE:
- ret = (oldval != cmparg);
- break;
- case FUTEX_OP_CMP_LT:
- ret = (oldval < cmparg);
- break;
- case FUTEX_OP_CMP_GE:
- ret = (oldval >= cmparg);
- break;
- case FUTEX_OP_CMP_LE:
- ret = (oldval <= cmparg);
- break;
- case FUTEX_OP_CMP_GT:
- ret = (oldval > cmparg);
- break;
- default:
- ret = -ENOSYS;
- }
-
- return (ret);
-}
-
-static int
-futex_orl(int oparg, caddr_t uaddr, int *oldval)
-{
- uint32_t ua, ua_old;
-
- for (;;) {
- ua = ua_old = fuword32(uaddr);
- ua |= oparg;
- if (casuword32((void *)uaddr, ua_old, ua) == ua_old)
- return ua_old;
- }
-}
-
-static int
-futex_andl(int oparg, caddr_t uaddr, int *oldval)
-{
- uint32_t ua, ua_old;
-
- for (;;) {
- ua = ua_old = fuword32(uaddr);
- ua &= oparg;
- if (casuword32((void *)uaddr, ua_old, ua) == ua_old)
- return ua_old;
- }
-}
-
-static int
-futex_xorl(int oparg, caddr_t uaddr, int *oldval)
-{
- uint32_t ua, ua_old;
-
- for (;;) {
- ua = ua_old = fuword32(uaddr);
- ua ^= oparg;
- if (casuword32((void *)uaddr, ua_old, ua) == ua_old)
- return ua_old;
+ if (ret)
+ return (ret);
+
+ switch (cmp) {
+ case FUTEX_OP_CMP_EQ:
+ return (oldval == cmparg);
+ case FUTEX_OP_CMP_NE:
+ return (oldval != cmparg);
+ case FUTEX_OP_CMP_LT:
+ return (oldval < cmparg);
+ case FUTEX_OP_CMP_GE:
+ return (oldval >= cmparg);
+ case FUTEX_OP_CMP_LE:
+ return (oldval <= cmparg);
+ case FUTEX_OP_CMP_GT:
+ return (oldval > cmparg);
+ default:
+ return (-ENOSYS);
}
}
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index 1eaef539be20..e2a74bd89db7 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -231,9 +231,10 @@ amd64/linux32/linux32_dummy.c optional compat_linux32
amd64/linux32/linux32_locore.s optional compat_linux32 \
dependency "linux32_assym.h"
amd64/linux32/linux32_machdep.c optional compat_linux32
+amd64/linux32/linux32_support.s optional compat_linux32
amd64/linux32/linux32_sysent.c optional compat_linux32
amd64/linux32/linux32_sysvec.c optional compat_linux32
-compat/linux/linux_emul.c optional compat_linux32
+compat/linux/linux_emul.c optional compat_linux32
compat/linux/linux_file.c optional compat_linux32
compat/linux/linux_futex.c optional compat_linux32
compat/linux/linux_getcwd.c optional compat_linux32
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index d2999a61bbbb..15de89ae96e5 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -345,6 +345,7 @@ i386/linux/linux_locore.s optional compat_linux \
dependency "linux_assym.h"
i386/linux/linux_machdep.c optional compat_linux
i386/linux/linux_ptrace.c optional compat_linux
+i386/linux/linux_support.s optional compat_linux
i386/linux/linux_sysent.c optional compat_linux
i386/linux/linux_sysvec.c optional compat_linux
i386/pci/pci_bus.c optional pci
diff --git a/sys/conf/files.pc98 b/sys/conf/files.pc98
index e1caa4b09601..ccfe7ba88e37 100644
--- a/sys/conf/files.pc98
+++ b/sys/conf/files.pc98
@@ -221,6 +221,7 @@ i386/linux/linux_locore.s optional compat_linux \
dependency "linux_assym.h"
i386/linux/linux_machdep.c optional compat_linux
i386/linux/linux_ptrace.c optional compat_linux
+i386/linux/linux_support.s optional compat_linux
i386/linux/linux_sysent.c optional compat_linux
i386/linux/linux_sysvec.c optional compat_linux
i386/pci/pci_bus.c optional pci
diff --git a/sys/i386/i386/support.s b/sys/i386/i386/support.s
index 7d49f01ead47..0f3452560d9b 100644
--- a/sys/i386/i386/support.s
+++ b/sys/i386/i386/support.s
@@ -1513,51 +1513,6 @@ ENTRY(longjmp)
incl %eax
ret
-/*****************************************************************************/
-/* linux_futex support */
-/*****************************************************************************/
-
-futex_fault:
- movl $0,PCB_ONFAULT(%ecx)
- movl $-EFAULT,%eax
- ret
-
-ENTRY(futex_xchgl)
- movl PCPU(CURPCB),%ecx
- movl $futex_fault,PCB_ONFAULT(%ecx)
- movl 4(%esp),%eax
- movl 8(%esp),%edx
- cmpl $VM_MAXUSER_ADDRESS-4,%edx
- ja futex_fault
-
-#ifdef SMP
- lock
-#endif
- xchgl %eax,(%edx)
- movl 12(%esp),%edx
- movl %eax,(%edx)
- xorl %eax,%eax
- movl $0,PCB_ONFAULT(%ecx)
- ret
-
-ENTRY(futex_addl)
- movl PCPU(CURPCB),%ecx
- movl $futex_fault,PCB_ONFAULT(%ecx)
- movl 4(%esp),%eax
- movl 8(%esp),%edx
- cmpl $VM_MAXUSER_ADDRESS-4,%edx
- ja futex_fault
-
-#ifdef SMP
- lock
-#endif
- xaddl %eax,(%edx)
- movl 12(%esp),%edx
- movl %eax,(%edx)
- xorl %eax,%eax
- movl $0,PCB_ONFAULT(%ecx)
- ret
-
/*
* Support for BB-profiling (gcc -a). The kernbb program will extract
* the data from the kernel.
diff --git a/sys/i386/linux/linux_support.s b/sys/i386/linux/linux_support.s
new file mode 100644
index 000000000000..171d6e739595
--- /dev/null
+++ b/sys/i386/linux/linux_support.s
@@ -0,0 +1,127 @@
+/*-
+ * Copyright (c) 2006,2007 Konstantin Belousov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "linux_assym.h" /* system definitions */
+#include <machine/asmacros.h> /* miscellaneous asm macros */
+
+#include "assym.s"
+
+futex_fault_decx:
+ movl PCPU(CURPCB),%ecx
+futex_fault:
+ movl $0,PCB_ONFAULT(%ecx)
+ movl $-EFAULT,%eax
+ ret
+
+ENTRY(futex_xchgl)
+ movl PCPU(CURPCB),%ecx
+ movl $futex_fault,PCB_ONFAULT(%ecx)
+ movl 4(%esp),%eax
+ movl 8(%esp),%edx
+ cmpl $VM_MAXUSER_ADDRESS-4,%edx
+ ja futex_fault
+ xchgl %eax,(%edx)
+ movl 12(%esp),%edx
+ movl %eax,(%edx)
+ xorl %eax,%eax
+ movl %eax,PCB_ONFAULT(%ecx)
+ ret
+
+ENTRY(futex_addl)
+ movl PCPU(CURPCB),%ecx
+ movl $futex_fault,PCB_ONFAULT(%ecx)
+ movl 4(%esp),%eax
+ movl 8(%esp),%edx
+ cmpl $VM_MAXUSER_ADDRESS-4,%edx
+ ja futex_fault
+#ifdef SMP
+ lock
+#endif
+ xaddl %eax,(%edx)
+ movl 12(%esp),%edx
+ movl %eax,(%edx)
+ xorl %eax,%eax
+ movl %eax,PCB_ONFAULT(%ecx)
+ ret
+
+ENTRY(futex_orl)
+ movl PCPU(CURPCB),%ecx
+ movl $futex_fault_decx,PCB_ONFAULT(%ecx)
+ movl 8(%esp),%edx
+ cmpl $VM_MAXUSER_ADDRESS-4,%edx
+ ja futex_fault
+ movl (%edx),%eax
+1: movl %eax,%ecx
+ orl 4(%esp),%ecx
+#ifdef SMP
+ lock
+#endif
+ cmpxchgl %ecx,(%edx)
+ jnz 1b
+futex_tail:
+ movl 12(%esp),%edx
+ movl %eax,(%edx)
+ xorl %eax,%eax
+ movl PCPU(CURPCB),%ecx
+ movl %eax,PCB_ONFAULT(%ecx)
+ ret
+
+ENTRY(futex_andl)
+ movl PCPU(CURPCB),%ecx
+ movl $futex_fault_decx,PCB_ONFAULT(%ecx)
+ movl 8(%esp),%edx
+ cmpl $VM_MAXUSER_ADDRESS-4,%edx
+ ja futex_fault
+ movl (%edx),%eax
+1: movl %eax,%ecx
+ andl 4(%esp),%ecx
+#ifdef SMP
+ lock
+#endif
+ cmpxchgl %ecx,(%edx)
+ jnz 1b
+ jmp futex_tail
+
+ENTRY(futex_xorl)
+ movl PCPU(CURPCB),%ecx
+ movl $futex_fault_decx,PCB_ONFAULT(%ecx)
+ movl 8(%esp),%edx
+ cmpl $VM_MAXUSER_ADDRESS-4,%edx
+ ja futex_fault
+ movl (%edx),%eax
+1: movl %eax,%ecx
+ xorl 4(%esp),%ecx
+#ifdef SMP
+ lock
+#endif
+ cmpxchgl %ecx,(%edx)
+ jnz 1b
+ jmp futex_tail
diff --git a/sys/modules/linux/Makefile b/sys/modules/linux/Makefile
index 123047038388..5d956d99d74e 100644
--- a/sys/modules/linux/Makefile
+++ b/sys/modules/linux/Makefile
@@ -14,8 +14,12 @@ SRCS= linux${SFX}_dummy.c linux_emul.c linux_file.c \
linux_socket.c linux_stats.c linux_sysctl.c linux${SFX}_sysent.c \
linux${SFX}_sysvec.c linux_uid16.c linux_util.c linux_time.c \
opt_inet6.h opt_mac.h opt_compat.h opt_posix.h vnode_if.h \
- device_if.h bus_if.h
-OBJS= linux${SFX}_locore.o
+ device_if.h bus_if.h assym.s
+
+# XXX: for assym.s
+SRCS+= opt_kstack_pages.h opt_nfs.h opt_apic.h opt_compat.h
+
+OBJS= linux${SFX}_locore.o linux${SFX}_support.o
.if ${MACHINE_ARCH} == "i386"
SRCS+= linux_ptrace.c imgact_linux.c opt_cpu.h
@@ -41,6 +45,10 @@ linux${SFX}_locore.o: linux${SFX}_locore.s linux${SFX}_assym.h
${CC} -c -x assembler-with-cpp -DLOCORE ${CFLAGS} \
${.IMPSRC} -o ${.TARGET}
+linux${SFX}_support.o: linux${SFX}_support.s assym.s
+ ${CC} -c -x assembler-with-cpp -DLOCORE ${CFLAGS} \
+ ${.IMPSRC} -o ${.TARGET}
+
linux${SFX}_genassym.o: linux${SFX}_genassym.c linux.h @ machine
${CC} -c ${CFLAGS:N-fno-common} ${.IMPSRC}