LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH] cancel_delayed_work: use del_timer() instead of del_timer_sync()
@ 2007-04-24 21:50 Oleg Nesterov
  2007-04-25 10:04 ` David Howells
  2007-04-25 13:02 ` Jarek Poplawski
  0 siblings, 2 replies; 8+ messages in thread
From: Oleg Nesterov @ 2007-04-24 21:50 UTC (permalink / raw)
  To: Andrew Morton
  Cc: David Howells, David Miller, Ingo Molnar, Jarek Poplawski, linux-kernel

del_timer_sync() buys nothing for cancel_delayed_work(), but it is less
efficient since it locks the timer unconditionally, and may wait for the
completion of the delayed_work_timer_fn().

cancel_delayed_work() == 0 means:

	before this patch:
		work->func may still be running or queued

	after this patch:
		work->func may still be running or queued, or
		delayed_work_timer_fn->__queue_work() in progress.

		The latter doesn't differ from the caller's POV,
		delayed_work_timer_fn() is called with _PENDING
		bit set.

cancel_delayed_work() == 1 with this patch adds a new possibility:

	delayed_work->work was cancelled, but delayed_work_timer_fn
	is still running (this is only possible for the re-arming
	works on single-threaded workqueue).

	In this case the timer was re-started by work->func(), nobody
	else can do this. This in turn means that delayed_work_timer_fn
	has already passed __queue_work() (and wont't touch delayed_work)
	because nobody else can queue delayed_work->work.

Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>

--- OLD/include/linux/workqueue.h~2_CDW	2007-04-05 12:20:35.000000000 +0400
+++ OLD/include/linux/workqueue.h	2007-04-25 01:48:24.000000000 +0400
@@ -152,14 +152,15 @@ extern void cancel_work_sync(struct work
 
 /*
  * Kill off a pending schedule_delayed_work().  Note that the work callback
- * function may still be running on return from cancel_delayed_work().  Run
- * flush_workqueue() or cancel_work_sync() to wait on it.
+ * function may still be running on return from cancel_delayed_work(), unless
+ * it returns 1 and the work doesn't re-arm itself. Run flush_workqueue() or
+ * cancel_work_sync() to wait on it.
  */
 static inline int cancel_delayed_work(struct delayed_work *work)
 {
 	int ret;
 
-	ret = del_timer_sync(&work->timer);
+	ret = del_timer(&work->timer);
 	if (ret)
 		work_clear_pending(&work->work);
 	return ret;


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2007-04-27  7:23 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-04-24 21:50 [PATCH] cancel_delayed_work: use del_timer() instead of del_timer_sync() Oleg Nesterov
2007-04-25 10:04 ` David Howells
2007-04-25 13:02 ` Jarek Poplawski
2007-04-25 12:52   ` Oleg Nesterov
2007-04-26 14:29     ` Jarek Poplawski
2007-04-26 15:29       ` Oleg Nesterov
2007-04-27  6:15         ` Jarek Poplawski
2007-04-27  7:23           ` Oleg Nesterov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).