|
@@ -1943,9 +1943,10 @@ static inline int fetch_robust_entry(struct robust_list __user **entry,
|
|
void exit_robust_list(struct task_struct *curr)
|
|
void exit_robust_list(struct task_struct *curr)
|
|
{
|
|
{
|
|
struct robust_list_head __user *head = curr->robust_list;
|
|
struct robust_list_head __user *head = curr->robust_list;
|
|
- struct robust_list __user *entry, *pending;
|
|
|
|
- unsigned int limit = ROBUST_LIST_LIMIT, pi, pip;
|
|
|
|
|
|
+ struct robust_list __user *entry, *next_entry, *pending;
|
|
|
|
+ unsigned int limit = ROBUST_LIST_LIMIT, pi, next_pi, pip;
|
|
unsigned long futex_offset;
|
|
unsigned long futex_offset;
|
|
|
|
+ int rc;
|
|
|
|
|
|
/*
|
|
/*
|
|
* Fetch the list head (which was registered earlier, via
|
|
* Fetch the list head (which was registered earlier, via
|
|
@@ -1965,11 +1966,13 @@ void exit_robust_list(struct task_struct *curr)
|
|
if (fetch_robust_entry(&pending, &head->list_op_pending, &pip))
|
|
if (fetch_robust_entry(&pending, &head->list_op_pending, &pip))
|
|
return;
|
|
return;
|
|
|
|
|
|
- if (pending)
|
|
|
|
- handle_futex_death((void __user *)pending + futex_offset,
|
|
|
|
- curr, pip);
|
|
|
|
-
|
|
|
|
|
|
+ next_entry = NULL; /* avoid warning with gcc */
|
|
while (entry != &head->list) {
|
|
while (entry != &head->list) {
|
|
|
|
+ /*
|
|
|
|
+ * Fetch the next entry in the list before calling
|
|
|
|
+ * handle_futex_death:
|
|
|
|
+ */
|
|
|
|
+ rc = fetch_robust_entry(&next_entry, &entry->next, &next_pi);
|
|
/*
|
|
/*
|
|
* A pending lock might already be on the list, so
|
|
* A pending lock might already be on the list, so
|
|
* don't process it twice:
|
|
* don't process it twice:
|
|
@@ -1978,11 +1981,10 @@ void exit_robust_list(struct task_struct *curr)
|
|
if (handle_futex_death((void __user *)entry + futex_offset,
|
|
if (handle_futex_death((void __user *)entry + futex_offset,
|
|
curr, pi))
|
|
curr, pi))
|
|
return;
|
|
return;
|
|
- /*
|
|
|
|
- * Fetch the next entry in the list:
|
|
|
|
- */
|
|
|
|
- if (fetch_robust_entry(&entry, &entry->next, &pi))
|
|
|
|
|
|
+ if (rc)
|
|
return;
|
|
return;
|
|
|
|
+ entry = next_entry;
|
|
|
|
+ pi = next_pi;
|
|
/*
|
|
/*
|
|
* Avoid excessively long or circular lists:
|
|
* Avoid excessively long or circular lists:
|
|
*/
|
|
*/
|
|
@@ -1991,6 +1993,10 @@ void exit_robust_list(struct task_struct *curr)
|
|
|
|
|
|
cond_resched();
|
|
cond_resched();
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ if (pending)
|
|
|
|
+ handle_futex_death((void __user *)pending + futex_offset,
|
|
|
|
+ curr, pip);
|
|
}
|
|
}
|
|
|
|
|
|
long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
|
|
long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
|