From: Ingo Molnar Date: Mon, 27 Mar 2006 09:16:27 +0000 (-0800) Subject: [PATCH] lightweight robust futexes updates X-Git-Tag: v2.6.17-rc1~377 X-Git-Url: http://pilppa.com/gitweb/?a=commitdiff_plain;h=8f17d3a5049d32392b79925c73a0cf99ce6d5af0;p=linux-2.6-omap-h63xx.git [PATCH] lightweight robust futexes updates - fix: initialize the robust list(s) to NULL in copy_process. - doc update - cleanup: rename _inuser to _inatomic - __user cleanups and other small cleanups Signed-off-by: Ingo Molnar Cc: Thomas Gleixner Cc: Arjan van de Ven Cc: Ulrich Drepper Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- diff --git a/Documentation/robust-futex-ABI.txt b/Documentation/robust-futex-ABI.txt index def5d873528..8529a17ffaa 100644 --- a/Documentation/robust-futex-ABI.txt +++ b/Documentation/robust-futex-ABI.txt @@ -142,8 +142,6 @@ On insertion: of the 'lock word', to the linked list starting at 'head', and 4) clear the 'list_op_pending' word. - XXX I am particularly unsure of the following -pj XXX - On removal: 1) set the 'list_op_pending' word to the address of the 'lock word' to be removed, diff --git a/Documentation/robust-futexes.txt b/Documentation/robust-futexes.txt index 7aecc67b136..df82d75245a 100644 --- a/Documentation/robust-futexes.txt +++ b/Documentation/robust-futexes.txt @@ -213,6 +213,6 @@ robust-mutex testcases. All other architectures should build just fine too - but they wont have the new syscalls yet. -Architectures need to implement the new futex_atomic_cmpxchg_inuser() +Architectures need to implement the new futex_atomic_cmpxchg_inatomic() inline function before writing up the syscalls (that function returns -ENOSYS right now). diff --git a/include/asm-frv/futex.h b/include/asm-frv/futex.h index 9a0e9026ba5..08b3d1da358 100644 --- a/include/asm-frv/futex.h +++ b/include/asm-frv/futex.h @@ -10,7 +10,7 @@ extern int futex_atomic_op_inuser(int encoded_op, int __user *uaddr); static inline int -futex_atomic_cmpxchg_inuser(int __user *uaddr, int oldval, int newval) +futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) { return -ENOSYS; } diff --git a/include/asm-generic/futex.h b/include/asm-generic/futex.h index 514bd401cd7..df893c16031 100644 --- a/include/asm-generic/futex.h +++ b/include/asm-generic/futex.h @@ -50,7 +50,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) } static inline int -futex_atomic_cmpxchg_inuser(int __user *uaddr, int oldval, int newval) +futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) { return -ENOSYS; } diff --git a/include/asm-i386/futex.h b/include/asm-i386/futex.h index 41184a31885..7b8ceefd010 100644 --- a/include/asm-i386/futex.h +++ b/include/asm-i386/futex.h @@ -105,7 +105,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) } static inline int -futex_atomic_cmpxchg_inuser(int __user *uaddr, int oldval, int newval) +futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) { if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) return -EFAULT; diff --git a/include/asm-mips/futex.h b/include/asm-mips/futex.h index c5fb2d6d918..a554089991f 100644 --- a/include/asm-mips/futex.h +++ b/include/asm-mips/futex.h @@ -100,7 +100,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) } static inline int -futex_atomic_cmpxchg_inuser(int __user *uaddr, int oldval, int newval) +futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) { return -ENOSYS; } diff --git a/include/asm-powerpc/futex.h b/include/asm-powerpc/futex.h index 80ed9854e42..f1b3c00bc1c 100644 --- a/include/asm-powerpc/futex.h +++ b/include/asm-powerpc/futex.h @@ -82,7 +82,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr) } static inline int -futex_atomic_cmpxchg_inuser(int __user *uaddr, int oldval, int newval) +futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) { return -ENOSYS; } diff --git a/include/asm-x86_64/futex.h b/include/asm-x86_64/futex.h index 7d9eb1a8454..9804bf07b09 100644 --- a/include/asm-x86_64/futex.h +++ b/include/asm-x86_64/futex.h @@ -95,7 +95,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) } static inline int -futex_atomic_cmpxchg_inuser(int __user *uaddr, int oldval, int newval) +futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) { if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) return -EFAULT; diff --git a/include/linux/futex.h b/include/linux/futex.h index 20face6b798..55fff96ae85 100644 --- a/include/linux/futex.h +++ b/include/linux/futex.h @@ -100,7 +100,7 @@ long do_futex(unsigned long uaddr, int op, int val, unsigned long timeout, unsigned long uaddr2, int val2, int val3); -extern int handle_futex_death(unsigned int *uaddr, struct task_struct *curr); +extern int handle_futex_death(u32 __user *uaddr, struct task_struct *curr); #ifdef CONFIG_FUTEX extern void exit_robust_list(struct task_struct *curr); diff --git a/kernel/fork.c b/kernel/fork.c index e0a2b449dea..c49bd193b05 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1061,7 +1061,10 @@ static task_t *copy_process(unsigned long clone_flags, * Clear TID on mm_release()? */ p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr: NULL; - + p->robust_list = NULL; +#ifdef CONFIG_COMPAT + p->compat_robust_list = NULL; +#endif /* * sigaltstack should be cleared when sharing the same VM */ diff --git a/kernel/futex.c b/kernel/futex.c index feb724b2554..9c9b2b6b22d 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -913,15 +913,15 @@ err_unlock: * Process a futex-list entry, check whether it's owned by the * dying task, and do notification if so: */ -int handle_futex_death(unsigned int *uaddr, struct task_struct *curr) +int handle_futex_death(u32 __user *uaddr, struct task_struct *curr) { - unsigned int futex_val; + u32 uval; -repeat: - if (get_user(futex_val, uaddr)) +retry: + if (get_user(uval, uaddr)) return -1; - if ((futex_val & FUTEX_TID_MASK) == curr->pid) { + if ((uval & FUTEX_TID_MASK) == curr->pid) { /* * Ok, this dying thread is truly holding a futex * of interest. Set the OWNER_DIED bit atomically @@ -932,12 +932,11 @@ repeat: * thread-death.) The rest of the cleanup is done in * userspace. */ - if (futex_atomic_cmpxchg_inuser(uaddr, futex_val, - futex_val | FUTEX_OWNER_DIED) != - futex_val) - goto repeat; + if (futex_atomic_cmpxchg_inatomic(uaddr, uval, + uval | FUTEX_OWNER_DIED) != uval) + goto retry; - if (futex_val & FUTEX_WAITERS) + if (uval & FUTEX_WAITERS) futex_wake((unsigned long)uaddr, 1); } return 0; @@ -985,7 +984,6 @@ void exit_robust_list(struct task_struct *curr) if (handle_futex_death((void *)entry + futex_offset, curr)) return; - /* * Fetch the next entry in the list: */ diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c index c153559ef28..9c077cf9aa8 100644 --- a/kernel/futex_compat.c +++ b/kernel/futex_compat.c @@ -121,9 +121,9 @@ err_unlock: return ret; } -asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, int val, +asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val, struct compat_timespec __user *utime, u32 __user *uaddr2, - int val3) + u32 val3) { struct timespec t; unsigned long timeout = MAX_SCHEDULE_TIMEOUT; @@ -137,6 +137,5 @@ asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, int val, if (op >= FUTEX_REQUEUE) val2 = (int) (unsigned long) utime; - return do_futex((unsigned long)uaddr, op, val, timeout, - (unsigned long)uaddr2, val2, val3); + return do_futex(uaddr, op, val, timeout, uaddr2, val2, val3); }