Messages in this thread Patch in this message |  | | | Date | Tue, 8 Oct 2002 17:26:09 +0200 (CEST) | | From | Ingo Molnar <> | | Subject | [patch] futex-2.5.41-A2 |
| |
the attached patch, mostly done by Martin Wirth, fixes the following bugs in the futex/vcache code:
- futex_close did not detach from the vcache. Detach cleanups. (Martin Wirth)
- __attach_vcache() now uses list_add_tail() to avoid the reversal of the futex queue if a COW happens. (Martin Wirth)
- the fastpath in __pin_page() now handles reserved pages the same way get_user_pages() does. (Martin Wirth)
- comment update to make it clear how the vcache hash quickcheck works.
patch compiles, boots & works just fine on x86 UP and SMP.
Ingo
--- linux/include/linux/vcache.h.orig 2002-10-08 10:18:45.000000000 +0200 +++ linux/include/linux/vcache.h 2002-10-08 17:01:26.000000000 +0200 @@ -18,7 +18,7 @@ struct mm_struct *mm, void (*callback)(struct vcache_s *data, struct page *new_page)); -extern void detach_vcache(vcache_t *vcache); +extern void __detach_vcache(vcache_t *vcache); extern void invalidate_vcache(unsigned long address, struct mm_struct *mm, struct page *new_page); --- linux/kernel/futex.c.orig 2002-10-08 10:18:49.000000000 +0200 +++ linux/kernel/futex.c 2002-10-08 17:01:26.000000000 +0200 @@ -115,8 +115,9 @@ * Do a quick atomic lookup first - this is the fastpath. */ page = follow_page(mm, addr, 0); - if (likely(page != NULL)) { - get_page(page); + if (likely(page != NULL)) { + if (!PageReserved(page)) + get_page(page); return page; } @@ -176,6 +177,7 @@ if (this->page == page && this->offset == offset) { list_del_init(i); + __detach_vcache(&this->vcache); tell_waiter(this); ret++; if (ret >= num) @@ -235,15 +237,18 @@ { int ret = 0; - detach_vcache(&q->vcache); + if (list_empty(&q->list)) + return ret; + spin_lock(&vcache_lock); spin_lock(&futex_lock); if (!list_empty(&q->list)) { list_del(&q->list); + __detach_vcache(&q->vcache); ret = 1; } spin_unlock(&futex_lock); - + spin_unlock(&vcache_lock); return ret; } @@ -314,13 +319,7 @@ { struct futex_q *q = filp->private_data; - spin_lock(&futex_lock); - if (!list_empty(&q->list)) { - list_del(&q->list); - /* Noone can be polling on us now. */ - BUG_ON(waitqueue_active(&q->waiters)); - } - spin_unlock(&futex_lock); + unqueue_me(q); unpin_page(q->page); kfree(filp->private_data); return 0; --- linux/mm/vcache.c.orig 2002-10-08 10:18:45.000000000 +0200 +++ linux/mm/vcache.c 2002-10-08 17:04:57.000000000 +0200 @@ -41,14 +41,12 @@ hash_head = hash_vcache(address, mm); - list_add(&vcache->hash_entry, hash_head); + list_add_tail(&vcache->hash_entry, hash_head); } -void detach_vcache(vcache_t *vcache) +void __detach_vcache(vcache_t *vcache) { - spin_lock(&vcache_lock); - list_del(&vcache->hash_entry); - spin_unlock(&vcache_lock); + list_del_init(&vcache->hash_entry); } void invalidate_vcache(unsigned long address, struct mm_struct *mm, @@ -61,12 +59,11 @@ hash_head = hash_vcache(address, mm); /* - * This is safe, because this path is called with the mm - * semaphore read-held, and the add/remove path calls with the - * mm semaphore write-held. So while other mm's might add new - * entries in parallel, and *this* mm is locked out, so if the - * list is empty now then we do not have to take the vcache - * lock to see it's really empty. + * This is safe, because this path is called with the pagetable + * lock held. So while other mm's might add new entries in + * parallel, *this* mm is locked out, so if the list is empty + * now then we do not have to take the vcache lock to see it's + * really empty. */ if (likely(list_empty(hash_head))) return; - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
|  |