diff options
| author | David S. Miller <davem@nuts.ninka.net> | 2002-10-15 07:41:35 -0700 |
|---|---|---|
| committer | David S. Miller <davem@nuts.ninka.net> | 2002-10-15 07:41:35 -0700 |
| commit | 8fbfe7cd5594010a23cb4e81786d1fb8015ffdee (patch) | |
| tree | b5be190f22984395209823ec3cac1c76fc93f67f /kernel/futex.c | |
| parent | e22f7f5fd43205bfd20ea3a7bb4e689cb3f3d278 (diff) | |
| parent | 5a7728c6d3eb83df9d120944cca4cf476dd326a1 (diff) | |
Merge nuts.ninka.net:/home/davem/src/BK/network-2.5
into nuts.ninka.net:/home/davem/src/BK/net-2.5
Diffstat (limited to 'kernel/futex.c')
| -rw-r--r-- | kernel/futex.c | 29 |
1 files changed, 13 insertions, 16 deletions
diff --git a/kernel/futex.c b/kernel/futex.c index d268c3c1b758..4aa2115c4d66 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -115,8 +115,9 @@ static struct page *__pin_page(unsigned long addr) * 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; } @@ -140,8 +141,10 @@ repeat_lookup: * check for races: */ tmp = follow_page(mm, addr, 0); - if (tmp != page) + if (tmp != page) { + put_page(page); goto repeat_lookup; + } return page; } @@ -176,6 +179,7 @@ static int futex_wake(unsigned long uaddr, int offset, int num) if (this->page == page && this->offset == offset) { list_del_init(i); + __detach_vcache(&this->vcache); tell_waiter(this); ret++; if (ret >= num) @@ -235,15 +239,15 @@ static inline int unqueue_me(struct futex_q *q) { int ret = 0; - detach_vcache(&q->vcache); - + 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 +318,7 @@ static int futex_close(struct inode *inode, struct file *filp) { 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; @@ -436,9 +434,8 @@ asmlinkage int sys_futex(unsigned long uaddr, int op, int val, struct timespec * pos_in_page = uaddr % PAGE_SIZE; - /* Must be "naturally" aligned, and not on page boundary. */ - if ((pos_in_page % __alignof__(int)) != 0 - || pos_in_page + sizeof(int) > PAGE_SIZE) + /* Must be "naturally" aligned */ + if (pos_in_page % sizeof(int)) return -EINVAL; switch (op) { |
