[LWN Logo]
[Timeline]
Date:	Wed, 31 Jan 2001 09:14:30 +0000 (GMT)
From:	David Woodhouse <dwmw2@infradead.org>
To:	Timur Tabi <ttabi@interactivesi.com>
Subject: Re: [ANNOUNCE] Kernel Janitor's TODO list

On Tue, 30 Jan 2001, Timur Tabi wrote:

> > If you have a task that looks like:
> > 
> >     loop:
> >         <do something important>
> >         sleep_on(q)
> > 
> > And you do wakeup(q) hoping to get something important done, then if the
> > task isn't sleeping at the time of the wakeup it will ignore the wakeup
> > and go to sleep, which imay not be what you wanted.
> 
> Ok, so how should this code have been written?

DECLARE_WAIT_QUEUE(wait, current);

while(1) {
	do_something_important()

	set_current_state(TASK_INTERRUPTIBLE);
	add_wait_queue(&q, &wait);

	/* Now if something arrives, we'll be 'woken' immediately -
	   - that is; our state will be set to TASK_RUNNING */

	if (!stuff_to_do()) {
		/* If the 'stuff' arrives here, we get woken anyway,
			so the schedule() returns immediately. You 
			can use schedule_timeout() here if you need
			a timeout, obviously */
		schedule();
	}

	set_current_state(TASK_RUNNING);
	remove_wait_queue(&q, &wait);

	if (signal_pending(current)) {
		/* You've been signalled. Deal with it. If you don't 
			want signals to wake you, use TASK_UNINTERRUPTIBLE
			above instead of TASK_INTERRUPTIBLE. Be aware
			that you'll add one to the load average all the
			time your task is sleeping then. */
		return -EINTR;
	}
}	


Alternatively, you could up() a semaphore for each task that's do be done, 
and down() it again each time you remove one from the queue. 

-- 
dwmw2


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/