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
* Re: [PATCH] cancel_delayed_work: use del_timer() instead of del_timer_sync() 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 1 sibling, 0 replies; 8+ messages in thread From: David Howells @ 2007-04-25 10:04 UTC (permalink / raw) To: Oleg Nesterov Cc: Andrew Morton, David Miller, Ingo Molnar, Jarek Poplawski, linux-kernel Oleg Nesterov <oleg@tv-sign.ru> wrote: > 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(). Okay, this patch seems to work for me, though I'm not using any of the other related patches that are in the -mm tree (I modified this patch to compile directly on top of Linus's vanilla tree). Acked-By: David Howells <dhowells@redhat.com> ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] cancel_delayed_work: use del_timer() instead of del_timer_sync() 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 1 sibling, 1 reply; 8+ messages in thread From: Jarek Poplawski @ 2007-04-25 13:02 UTC (permalink / raw) To: Oleg Nesterov Cc: Andrew Morton, David Howells, David Miller, Ingo Molnar, linux-kernel On Wed, Apr 25, 2007 at 01:50:34AM +0400, Oleg Nesterov wrote: > 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(). I'm not sure what is the main aim of this patch. It seems this change cannot do any harm, but anyway it could change a few things, e.g. with current version of cancel_rearming_delayed_work some flush_workqueue could be done needlessly, before the work is queued from timer. It's not a big deal here, but if anybody did something like this without loop - it could matter. So, probably a lot of current code should be checked, before applying and I doubt the gain is worth of this. Maybe, for safety, make this with new name as an alternative and deprecate the current version? Regards, Jarek P. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] cancel_delayed_work: use del_timer() instead of del_timer_sync() 2007-04-25 13:02 ` Jarek Poplawski @ 2007-04-25 12:52 ` Oleg Nesterov 2007-04-26 14:29 ` Jarek Poplawski 0 siblings, 1 reply; 8+ messages in thread From: Oleg Nesterov @ 2007-04-25 12:52 UTC (permalink / raw) To: Jarek Poplawski Cc: Andrew Morton, David Howells, David Miller, Ingo Molnar, linux-kernel On 04/25, Jarek Poplawski wrote: > > On Wed, Apr 25, 2007 at 01:50:34AM +0400, Oleg Nesterov wrote: > > 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(). > > I'm not sure what is the main aim of this patch. optimization > It seems this > change cannot do any harm, but anyway it could change a few > things, e.g. with current version of cancel_rearming_delayed_work > some flush_workqueue could be done needlessly, before the work > is queued from timer. I don't think so... Could you clarify? > It's not a big deal here, but if anybody > did something like this without loop - it could matter. > > So, probably a lot of current code should be checked, before > applying and I doubt the gain is worth of this. Maybe, for > safety, make this with new name as an alternative and > deprecate the current version? This change should not make any visible difference for the callers, otherwise it is buggy. Oleg. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] cancel_delayed_work: use del_timer() instead of del_timer_sync() 2007-04-25 12:52 ` Oleg Nesterov @ 2007-04-26 14:29 ` Jarek Poplawski 2007-04-26 15:29 ` Oleg Nesterov 0 siblings, 1 reply; 8+ messages in thread From: Jarek Poplawski @ 2007-04-26 14:29 UTC (permalink / raw) To: Oleg Nesterov Cc: Andrew Morton, David Howells, David Miller, Ingo Molnar, linux-kernel On Wed, Apr 25, 2007 at 04:52:14PM +0400, Oleg Nesterov wrote: > On 04/25, Jarek Poplawski wrote: > > > > On Wed, Apr 25, 2007 at 01:50:34AM +0400, Oleg Nesterov wrote: > > > 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(). > > > > I'm not sure what is the main aim of this patch. > > optimization > > > It seems this > > change cannot do any harm, but anyway it could change a few > > things, e.g. with current version of cancel_rearming_delayed_work > > some flush_workqueue could be done needlessly, before the work > > is queued from timer. > > I don't think so... Could you clarify? With a code like: if (!cancel_delayed_work(dwork)) flush_workqueue(wq); if cancel_ returns 0, and there is _queue_work in progress, flush_ will be done once, after this work is queued. After the patch, and the same situation flush_ also runs one time, but maybe without the work in a queue. So, if there is no more loops, there could be difference, and even if very unprobable, something could stop working after such change. > > > It's not a big deal here, but if anybody > > did something like this without loop - it could matter. > > > > So, probably a lot of current code should be checked, before > > applying and I doubt the gain is worth of this. Maybe, for > > safety, make this with new name as an alternative and > > deprecate the current version? > > This change should not make any visible difference for the callers, > otherwise it is buggy. IMHO, there is the same visible difference, as between del_timer and del_timer_sync. Regards, Jarek P. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] cancel_delayed_work: use del_timer() instead of del_timer_sync() 2007-04-26 14:29 ` Jarek Poplawski @ 2007-04-26 15:29 ` Oleg Nesterov 2007-04-27 6:15 ` Jarek Poplawski 0 siblings, 1 reply; 8+ messages in thread From: Oleg Nesterov @ 2007-04-26 15:29 UTC (permalink / raw) To: Jarek Poplawski Cc: Andrew Morton, David Howells, David Miller, Ingo Molnar, linux-kernel On 04/26, Jarek Poplawski wrote: > > On Wed, Apr 25, 2007 at 04:52:14PM +0400, Oleg Nesterov wrote: > > > > > It seems this > > > change cannot do any harm, but anyway it could change a few > > > things, e.g. with current version of cancel_rearming_delayed_work > > > some flush_workqueue could be done needlessly, before the work > > > is queued from timer. > > > > I don't think so... Could you clarify? > > With a code like: > > if (!cancel_delayed_work(dwork)) > flush_workqueue(wq); > > if cancel_ returns 0, and there is _queue_work in progress, > flush_ will be done once, after this work is queued. > > After the patch, and the same situation flush_ also runs > one time, but maybe without the work in a queue. First, this is very unlikely event, and the behaviour is correct, do you agree? Even in this case, it is very unlikely that flush_cpu_workqueue() will take cwq->lock before extremely short delayed_work_timer_fn. Even if it does, work->func() likely will be completed when the caller of flush_workqueue() will be woken by run_workquue() and gets CPU. Please also look at http://marc.info/?t=117699337200022&r=1 > > > It's not a big deal here, but if anybody > > > did something like this without loop - it could matter. > > > > > > So, probably a lot of current code should be checked, before > > > applying and I doubt the gain is worth of this. Maybe, for > > > safety, make this with new name as an alternative and > > > deprecate the current version? > > > > This change should not make any visible difference for the callers, > > otherwise it is buggy. > > IMHO, there is the same visible difference, > as between del_timer and del_timer_sync. Jarek, please, could you be more explicite ? del_timer() and del_timer_sync() are different in many ways. What exactly will impact the user of cancel_delaye_work ? Oleg. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] cancel_delayed_work: use del_timer() instead of del_timer_sync() 2007-04-26 15:29 ` Oleg Nesterov @ 2007-04-27 6:15 ` Jarek Poplawski 2007-04-27 7:23 ` Oleg Nesterov 0 siblings, 1 reply; 8+ messages in thread From: Jarek Poplawski @ 2007-04-27 6:15 UTC (permalink / raw) To: Oleg Nesterov Cc: Andrew Morton, David Howells, David Miller, Ingo Molnar, linux-kernel On Thu, Apr 26, 2007 at 07:29:53PM +0400, Oleg Nesterov wrote: > On 04/26, Jarek Poplawski wrote: ... > > > This change should not make any visible difference for the callers, > > > otherwise it is buggy. > > > > IMHO, there is the same visible difference, > > as between del_timer and del_timer_sync. > > Jarek, please, could you be more explicite ? del_timer() and > del_timer_sync() are different in many ways. What exactly will > impact the user of cancel_delaye_work ? OK, I changed my mind. Now, I think it's very probable this should matter... According to workqueue.h: > /* > * 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. > */ > static inline int cancel_delayed_work(struct delayed_work *work) So, we can do something like this: cancel_delayed_work(dwork); flush_workqueue(wq); kfree(some_obj_used_by_dwork_func); And this is enough to work with not rearming work. But no more after this patch... So, I think, your proposal should be alternative version, and current version should stay, so we have a choice. Just like del_timer and del_timer_sync. Jarek P. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] cancel_delayed_work: use del_timer() instead of del_timer_sync() 2007-04-27 6:15 ` Jarek Poplawski @ 2007-04-27 7:23 ` Oleg Nesterov 0 siblings, 0 replies; 8+ messages in thread From: Oleg Nesterov @ 2007-04-27 7:23 UTC (permalink / raw) To: Jarek Poplawski Cc: Andrew Morton, David Howells, David Miller, Ingo Molnar, linux-kernel On 04/27, Jarek Poplawski wrote: > > According to workqueue.h: > > /* > > * 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. > > */ > > static inline int cancel_delayed_work(struct delayed_work *work) > > So, we can do something like this: > > cancel_delayed_work(dwork); > flush_workqueue(wq); > kfree(some_obj_used_by_dwork_func); > > And this is enough to work with not rearming work. > > But no more after this patch... Yes, you are right, and so this patch is wrong. This is even documented in the changelog, with this change cancel_delayed_work() may return while the queueing is in progress. However, in that case we can not rely on flush_workqueue/cancel_work_sync. Thanks a lot! Oleg. ^ 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).