Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 75311
b: refs/heads/master
c: cdf71a1
h: refs/heads/master
i:
  75309: 7fa47a1
  75307: c1def75
  75303: 0c95a50
  75295: 52538ef
v: v3
  • Loading branch information
Thomas Gleixner authored and Linus Torvalds committed Jan 9, 2008
1 parent a032241 commit 6019084
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 11 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: bf5e5834bffc62b50cd4a201804506eb11ef1af8
refs/heads/master: cdf71a10c7b6432d9b48e292cca2c62a0b9fa6cf
51 changes: 41 additions & 10 deletions trunk/kernel/futex.c
Original file line number Diff line number Diff line change
Expand Up @@ -1097,15 +1097,15 @@ static void unqueue_me_pi(struct futex_q *q)
}

/*
* Fixup the pi_state owner with current.
* Fixup the pi_state owner with the new owner.
*
* Must be called with hash bucket lock held and mm->sem held for non
* private futexes.
*/
static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
struct task_struct *curr)
struct task_struct *newowner)
{
u32 newtid = task_pid_vnr(curr) | FUTEX_WAITERS;
u32 newtid = task_pid_vnr(newowner) | FUTEX_WAITERS;
struct futex_pi_state *pi_state = q->pi_state;
u32 uval, curval, newval;
int ret;
Expand All @@ -1119,12 +1119,12 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
} else
newtid |= FUTEX_OWNER_DIED;

pi_state->owner = curr;
pi_state->owner = newowner;

spin_lock_irq(&curr->pi_lock);
spin_lock_irq(&newowner->pi_lock);
WARN_ON(!list_empty(&pi_state->list));
list_add(&pi_state->list, &curr->pi_state_list);
spin_unlock_irq(&curr->pi_lock);
list_add(&pi_state->list, &newowner->pi_state_list);
spin_unlock_irq(&newowner->pi_lock);

/*
* We own it, so we have to replace the pending owner
Expand Down Expand Up @@ -1508,9 +1508,40 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
* when we were on the way back before we locked the
* hash bucket.
*/
if (q.pi_state->owner == curr &&
rt_mutex_trylock(&q.pi_state->pi_mutex)) {
ret = 0;
if (q.pi_state->owner == curr) {
/*
* Try to get the rt_mutex now. This might
* fail as some other task acquired the
* rt_mutex after we removed ourself from the
* rt_mutex waiters list.
*/
if (rt_mutex_trylock(&q.pi_state->pi_mutex))
ret = 0;
else {
/*
* pi_state is incorrect, some other
* task did a lock steal and we
* returned due to timeout or signal
* without taking the rt_mutex. Too
* late. We can access the
* rt_mutex_owner without locking, as
* the other task is now blocked on
* the hash bucket lock. Fix the state
* up.
*/
struct task_struct *owner;
int res;

owner = rt_mutex_owner(&q.pi_state->pi_mutex);
res = fixup_pi_state_owner(uaddr, &q, owner);

WARN_ON(rt_mutex_owner(&q.pi_state->pi_mutex) !=
owner);

/* propagate -EFAULT, if the fixup failed */
if (res)
ret = res;
}
} else {
/*
* Paranoia check. If we did not take the lock
Expand Down

0 comments on commit 6019084

Please sign in to comment.