[RFC PATCH 05/12] futex: Implement exit_ping_state_list().

From: Suleiman Souhlal

Date: Thu Sep 17 2026 - 00:34:42 EST


Handle the case when a task exits while holding some ping_states,
unowning them and dropping their references.

Signed-off-by: Suleiman Souhlal <suleiman@xxxxxxxxxx>
---
kernel/futex/core.c | 55 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 55 insertions(+)

diff --git a/kernel/futex/core.c b/kernel/futex/core.c
index 13c7ea3a26b3..56c7e2d5faac 100644
--- a/kernel/futex/core.c
+++ b/kernel/futex/core.c
@@ -1430,6 +1430,58 @@ static void exit_pi_state_list(struct task_struct *curr)
static inline void exit_pi_state_list(struct task_struct *curr) { }
#endif

+/* Similar to exit_pi_state_list() */
+static void exit_ping_state_list(struct task_struct *curr)
+{
+ struct list_head *next, *head = &curr->futex.ping_state_list;
+ struct futex_pi_state *ping_state;
+ union futex_key key = FUTEX_KEY_INIT;
+
+ might_sleep();
+ WARN_ON(curr != current);
+ guard(private_hash)(current->mm);
+
+ raw_spin_lock_irq(&curr->pi_futex_lock);
+ while (!list_empty(head)) {
+ next = head->next;
+ ping_state = list_entry(next, struct futex_pi_state, list);
+ if (1) {
+ CLASS(hbr, hbr)(&key);
+ auto hb = hbr.hb;
+
+ if (!refcount_inc_not_zero(&ping_state->refcount)) {
+ raw_spin_unlock_irq(&curr->pi_futex_lock);
+ cpu_relax();
+ raw_spin_lock_irq(&curr->pi_futex_lock);
+ continue;
+ }
+ raw_spin_unlock_irq(&curr->pi_futex_lock);
+
+ spin_lock(&hb->lock);
+ raw_spin_lock_irq(&ping_state->ping_mutex.wait_lock);
+ raw_spin_lock(&curr->pi_futex_lock);
+ if (head->next != next) {
+ raw_spin_unlock(&ping_state->ping_mutex.wait_lock);
+ spin_unlock(&hb->lock);
+ put_ping_state(ping_state);
+ continue;
+ }
+
+ WARN_ON(ping_state->owner != curr);
+ WARN_ON(list_empty(&ping_state->list));
+ list_del_init(&ping_state->list);
+ ping_state->owner = NULL;
+ raw_spin_unlock(&curr->pi_futex_lock);
+ raw_spin_unlock_irq(&ping_state->ping_mutex.wait_lock);
+ spin_unlock(&hb->lock);
+ }
+ put_ping_state(ping_state);
+
+ raw_spin_lock_irq(&curr->pi_futex_lock);
+ }
+ raw_spin_unlock_irq(&curr->pi_futex_lock);
+}
+
bool futex_robust_list_clear_pending(void __user *pop, unsigned int flags)
{
bool size32bit = !!(flags & FLAGS_ROBUST_LIST32);
@@ -1475,6 +1527,9 @@ static void futex_cleanup(struct task_struct *tsk)

if (unlikely(!list_empty(&tsk->futex.pi_state_list)))
exit_pi_state_list(tsk);
+
+ if (unlikely(!list_empty(&tsk->futex.ping_state_list)))
+ exit_ping_state_list(tsk);
}

/**
--
2.55.0.1082.g2b9226bbc0-goog