struct {
unsigned long pgoff;
struct inode *inode;
+ int offset;
} shared;
struct {
unsigned long uaddr;
struct mm_struct *mm;
+ int offset;
} private;
struct {
unsigned long word;
void *ptr;
+ int offset;
} both;
- int offset;
};
/*
{
return &futex_queues[hash_long(key->both.word
+ (unsigned long) key->both.ptr
- + key->offset, FUTEX_HASHBITS)];
+ + key->both.offset, FUTEX_HASHBITS)];
}
/*
{
return (key1->both.word == key2->both.word
&& key1->both.ptr == key2->both.ptr
- && key1->offset == key2->offset);
+ && key1->both.offset == key2->both.offset);
}
/*
/*
* The futex address must be "naturally" aligned.
*/
- key->offset = uaddr % PAGE_SIZE;
- if (unlikely((key->offset % sizeof(u32)) != 0))
+ key->both.offset = uaddr % PAGE_SIZE;
+ if (unlikely((key->both.offset % sizeof(u32)) != 0))
return -EINVAL;
- uaddr -= key->offset;
+ uaddr -= key->both.offset;
/*
* The futex is hashed differently depending on whether
key->shared.pgoff =
page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
put_page(page);
+ return 0;
}
return err;
}
* Wake up all waiters hashed on the physical page that is mapped
* to this virtual address:
*/
-static inline int futex_wake(unsigned long uaddr, int num)
+static int futex_wake(unsigned long uaddr, int num)
{
struct list_head *i, *next, *head;
union futex_key key;
* Requeue all waiters hashed on one physical page to another
* physical page.
*/
-static inline int futex_requeue(unsigned long uaddr1, unsigned long uaddr2,
+static int futex_requeue(unsigned long uaddr1, unsigned long uaddr2,
int nr_wake, int nr_requeue)
{
struct list_head *i, *next, *head1, *head2;
this->key = key2;
if (ret - nr_wake >= nr_requeue)
break;
+ /* Make sure to stop if key1 == key2 */
+ if (head1 == head2 && head1 != next)
+ head1 = i;
}
}
}
return ret;
}
-static inline int futex_wait(unsigned long uaddr, int val, unsigned long time)
+static int futex_wait(unsigned long uaddr, int val, unsigned long time)
{
DECLARE_WAITQUEUE(wait, current);
int ret, curval;