X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=kernel%2Ffutex.c;h=5efa2f978032d1f20955c5f99eb24bf0e1051c51;hb=ae7a49666af427da745e69a39fcfdd3a8b4ab3e8;hp=ca05fe6a70b24a2921901505c99dd7eb105b3df7;hpb=d7f6884ae0ae6e406ec3500fcde16e8f51642460;p=powerpc.git diff --git a/kernel/futex.c b/kernel/futex.c index ca05fe6a70..5efa2f9780 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -201,23 +201,6 @@ static int get_futex_key(unsigned long uaddr, union futex_key *key) * from swap. But that's a lot of code to duplicate here * for a rare case, so we simply fetch the page. */ - - /* - * Do a quick atomic lookup first - this is the fastpath. - */ - spin_lock(¤t->mm->page_table_lock); - page = follow_page(mm, uaddr, 0); - if (likely(page != NULL)) { - key->shared.pgoff = - page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); - spin_unlock(¤t->mm->page_table_lock); - return 0; - } - spin_unlock(¤t->mm->page_table_lock); - - /* - * Do it the general way. - */ err = get_user_pages(current, mm, uaddr, 1, 0, 0, &page, NULL); if (err >= 0) { key->shared.pgoff = @@ -287,7 +270,13 @@ static void wake_futex(struct futex_q *q) /* * The waiting task can free the futex_q as soon as this is written, * without taking any locks. This must come last. + * + * A memory barrier is required here to prevent the following store + * to lock_ptr from getting ahead of the wakeup. Clearing the lock + * at the end of wake_up_all() does not prevent this store from + * moving. */ + wmb(); q->lock_ptr = NULL; } @@ -367,6 +356,18 @@ retry: if (bh1 != bh2) spin_unlock(&bh2->lock); +#ifndef CONFIG_MMU + /* we don't get EFAULT from MMU faults if we don't have an MMU, + * but we might get them from range checking */ + ret = op_ret; + goto out; +#endif + + if (unlikely(op_ret != -EFAULT)) { + ret = op_ret; + goto out; + } + /* futex_atomic_op_inuser needs to both read and write * *(int __user *)uaddr2, but we can't modify it * non-atomically. Therefore, if get_user below is not