Messages in this thread | | | Date | Fri, 23 Jan 2009 14:30:50 +0100 | From | Oleg Nesterov <> | Subject | Re: [RFC v4] wait: prevent waiter starvation in __wait_on_bit_lock |
| |
On 01/23, Oleg Nesterov wrote: > > It is no that I think this new helper is really needed for this > particular case, personally I agree with the patch you sent. > > But if we have other places with the similar problem, then perhaps > it is better to introduce the special finish_wait_exclusive() or > whatever.
To clarify, I suggest something like this.
int finish_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int ret, int state, void *key) { unsigned long flags;
__set_current_state(TASK_RUNNING);
if (ret || !list_empty_careful(&wait->task_list)) { spin_lock_irqsave(&q->lock, flags); if (list_empty(&wait->task_list)) __wake_up_common(q, state, 1, key); else list_del_init(&wait->task_list); spin_unlock_irqrestore(&q->lock, flags); }
return ret; }
Now, __wait_on_bit_lock() becomes:
int __sched __wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q, int (*action)(void *), unsigned mode) { int ret = 0;
do { prepare_to_wait_exclusive(wq, &q->wait, mode); if (test_bit(q->key.bit_nr, q->key.flags) && (ret = (*action)(q->key.flags)) break; } while (test_and_set_bit(q->key.bit_nr, q->key.flags));
return finish_wait_exclusive(wq, &q->wait, ret, mode, &q->key); }
And __wait_event_interruptible_exclusive:
#define __wait_event_interruptible_exclusive(wq, condition, ret) \ do { \ DEFINE_WAIT(__wait); \ \ for (;;) { \ prepare_to_wait_exclusive(&wq, &__wait, \ TASK_INTERRUPTIBLE); \ if (condition) \ break; \ if (!signal_pending(current)) { \ schedule(); \ continue; \ } \ ret = -ERESTARTSYS; \ break; \ } \ finish_wait_exclusive(&wq, &__wait, \ ret, TASK_INTERRUPTIBLE, NULL); \ } while (0)
But I can't convince myself this is what we really want. So I am not sending the patch. And yes, we have to check ret twice.
Oleg.
| |