public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* workqueue and pending
@ 2004-05-03 11:39 Mikkel Christiansen
  2004-05-03 23:27 ` Andrew Morton
  0 siblings, 1 reply; 8+ messages in thread
From: Mikkel Christiansen @ 2004-05-03 11:39 UTC (permalink / raw)
  To: linux-kernel

Hi

We're trying to use the workqueue interface for scheduling a delayed 
gargage collector.
Since we only need a single delayed thread we used the DECLEARE_WORK macro.

The problem is that once we call cancel_delayed_work we can't schedule 
work again.

Having looked at the code i noticed that cancel_delayed_work only 
deletes the timer but
doesn't set clear the "pending" bit, thus any call to 
schedule_delayed_work is ignorred.

Example:

static DECLARE_WORK(tft, timeoutfun, NULL)
.
.
.
schedule_delayed_work(&tft, 1*HZ);
cancel_delayed_work(&tft);

<do some work>

tft.pending = 0;   / / if we dont clear pending no work can be scheduled
schedule_delayed_work(&tft, 1*HZ);
return 0;

End example

Setting tft.pending is a rather ugly solution - shouldn't it be cleared by
cancel_delayed_work?, or are we using the interface in the wrong way?

Cheers
    Mikkel



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

* Re: workqueue and pending
  2004-05-03 11:39 workqueue and pending Mikkel Christiansen
@ 2004-05-03 23:27 ` Andrew Morton
  2004-05-04  2:51   ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 8+ messages in thread
From: Andrew Morton @ 2004-05-03 23:27 UTC (permalink / raw)
  To: Mikkel Christiansen; +Cc: linux-kernel

Mikkel Christiansen <mixxel@cs.auc.dk> wrote:
>
> We're trying to use the workqueue interface for scheduling a delayed 
> gargage collector.
> Since we only need a single delayed thread we used the DECLEARE_WORK macro.
> 
> The problem is that once we call cancel_delayed_work we can't schedule 
> work again.

It looks like nobody has tried to do that yet.

> Having looked at the code i noticed that cancel_delayed_work only 
> deletes the timer but
> doesn't set clear the "pending" bit, thus any call to 
> schedule_delayed_work is ignorred.

Does this work?

--- 25/include/linux/workqueue.h~cancel_delayed_work-fix	Mon May  3 16:24:46 2004
+++ 25-akpm/include/linux/workqueue.h	Mon May  3 16:26:01 2004
@@ -7,6 +7,7 @@
 
 #include <linux/timer.h>
 #include <linux/linkage.h>
+#include <linux/bitops.h>
 
 struct workqueue_struct;
 
@@ -75,8 +76,11 @@ extern void init_workqueues(void);
  */
 static inline int cancel_delayed_work(struct work_struct *work)
 {
-	return del_timer_sync(&work->timer);
+	int ret;
+
+	ret = del_timer_sync(&work->timer);
+	clear_bit(0, &work->pending);
+	return ret;
 }
 
 #endif
-

_


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

* Re: workqueue and pending
  2004-05-03 23:27 ` Andrew Morton
@ 2004-05-04  2:51   ` Benjamin Herrenschmidt
  2004-05-04  3:16     ` Andrew Morton
  0 siblings, 1 reply; 8+ messages in thread
From: Benjamin Herrenschmidt @ 2004-05-04  2:51 UTC (permalink / raw)
  To: Andrew Morton; +Cc: Mikkel Christiansen, Linux Kernel list


>  
> @@ -75,8 +76,11 @@ extern void init_workqueues(void);
>   */
>  static inline int cancel_delayed_work(struct work_struct *work)
>  {
> -	return del_timer_sync(&work->timer);
> +	int ret;
> +
> +	ret = del_timer_sync(&work->timer);
> +	clear_bit(0, &work->pending);
> +	return ret;
>  }
>  

Looks wrong to me. The time may have fired already and queued the
work. Clearing pending is an error in this case since the work is
indeed pending for execution.... 

Ben.



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

* Re: workqueue and pending
  2004-05-04  2:51   ` Benjamin Herrenschmidt
@ 2004-05-04  3:16     ` Andrew Morton
  2004-05-04  3:55       ` Benjamin Herrenschmidt
  2004-05-04 13:36       ` Mikkel Christiansen
  0 siblings, 2 replies; 8+ messages in thread
From: Andrew Morton @ 2004-05-04  3:16 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: mixxel, linux-kernel

Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
>
> 
> >  
> > @@ -75,8 +76,11 @@ extern void init_workqueues(void);
> >   */
> >  static inline int cancel_delayed_work(struct work_struct *work)
> >  {
> > -	return del_timer_sync(&work->timer);
> > +	int ret;
> > +
> > +	ret = del_timer_sync(&work->timer);
> > +	clear_bit(0, &work->pending);
> > +	return ret;
> >  }
> >  
> 
> Looks wrong to me. The time may have fired already and queued the
> work. Clearing pending is an error in this case since the work is
> indeed pending for execution.... 

OK...

--- 25/include/linux/workqueue.h~cancel_delayed_work-fix	2004-05-03 20:14:26.796321416 -0700
+++ 25-akpm/include/linux/workqueue.h	2004-05-03 20:15:41.010039216 -0700
@@ -7,6 +7,7 @@
 
 #include <linux/timer.h>
 #include <linux/linkage.h>
+#include <linux/bitops.h>
 
 struct workqueue_struct;
 
@@ -75,8 +76,12 @@ extern void init_workqueues(void);
  */
 static inline int cancel_delayed_work(struct work_struct *work)
 {
-	return del_timer_sync(&work->timer);
+	int ret;
+
+	ret = del_timer_sync(&work->timer);
+	if (ret)
+		clear_bit(0, &work->pending);
+	return ret;
 }
 
 #endif
-

_


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

* Re: workqueue and pending
  2004-05-04  3:16     ` Andrew Morton
@ 2004-05-04  3:55       ` Benjamin Herrenschmidt
  2004-05-04  4:15         ` Andrew Morton
  2004-05-04 13:36       ` Mikkel Christiansen
  1 sibling, 1 reply; 8+ messages in thread
From: Benjamin Herrenschmidt @ 2004-05-04  3:55 UTC (permalink / raw)
  To: Andrew Morton; +Cc: mixxel, Linux Kernel list


>  static inline int cancel_delayed_work(struct work_struct *work)
>  {
> -	return del_timer_sync(&work->timer);
> +	int ret;
> +
> +	ret = del_timer_sync(&work->timer);
> +	if (ret)
> +		clear_bit(0, &work->pending);
> +	return ret;
>  }

Heh, I was trying to figure out a simple way to do that and just
didn't figure out del_timer_sync() would actually have a useful
return value :)

It's probably still good to precise explicitely in the comments
that upon return of cancel_delayed_work(), the work queue might
still be pending and that a flush and whoever called this may
still need a flush_scheduled_work() or flush_workqueue() (provided
it's running in a context where that can sleep)

Ben.



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

* Re: workqueue and pending
  2004-05-04  3:55       ` Benjamin Herrenschmidt
@ 2004-05-04  4:15         ` Andrew Morton
  2004-05-04  4:41           ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 8+ messages in thread
From: Andrew Morton @ 2004-05-04  4:15 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: mixxel, linux-kernel

Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
>
> It's probably still good to precise explicitely in the comments
>  that upon return of cancel_delayed_work(), the work queue might
>  still be pending and that a flush and whoever called this may
>  still need a flush_scheduled_work() or flush_workqueue() (provided
>  it's running in a context where that can sleep)

That function was originally written by a comment fetishist.

/*
 * 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_scheduled_work() to wait on it.
 */
static inline int cancel_delayed_work(struct work_struct *work)
{
	int ret;

	ret = del_timer_sync(&work->timer);
	if (ret)
		clear_bit(0, &work->pending);
	return ret;
}


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

* Re: workqueue and pending
  2004-05-04  4:15         ` Andrew Morton
@ 2004-05-04  4:41           ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 8+ messages in thread
From: Benjamin Herrenschmidt @ 2004-05-04  4:41 UTC (permalink / raw)
  To: Andrew Morton; +Cc: mixxel, Linux Kernel list

On Tue, 2004-05-04 at 14:15, Andrew Morton wrote:
> Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
> >
> > It's probably still good to precise explicitely in the comments
> >  that upon return of cancel_delayed_work(), the work queue might
> >  still be pending and that a flush and whoever called this may
> >  still need a flush_scheduled_work() or flush_workqueue() (provided
> >  it's running in a context where that can sleep)
> 
> That function was originally written by a comment fetishist.

Heh, I should have looked at the code =P

Ben.



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

* Re: workqueue and pending
  2004-05-04  3:16     ` Andrew Morton
  2004-05-04  3:55       ` Benjamin Herrenschmidt
@ 2004-05-04 13:36       ` Mikkel Christiansen
  1 sibling, 0 replies; 8+ messages in thread
From: Mikkel Christiansen @ 2004-05-04 13:36 UTC (permalink / raw)
  To: Andrew Morton; +Cc: Benjamin Herrenschmidt, linux-kernel

I tried the patch and it works fine

-Mikkel

Andrew Morton wrote:

>Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
>  
>
>>    
>>
>>> 
>>>@@ -75,8 +76,11 @@ extern void init_workqueues(void);
>>>  */
>>> static inline int cancel_delayed_work(struct work_struct *work)
>>> {
>>>-	return del_timer_sync(&work->timer);
>>>+	int ret;
>>>+
>>>+	ret = del_timer_sync(&work->timer);
>>>+	clear_bit(0, &work->pending);
>>>+	return ret;
>>> }
>>> 
>>>      
>>>
>>Looks wrong to me. The time may have fired already and queued the
>>work. Clearing pending is an error in this case since the work is
>>indeed pending for execution.... 
>>    
>>
>
>OK...
>
>--- 25/include/linux/workqueue.h~cancel_delayed_work-fix	2004-05-03 20:14:26.796321416 -0700
>+++ 25-akpm/include/linux/workqueue.h	2004-05-03 20:15:41.010039216 -0700
>@@ -7,6 +7,7 @@
> 
> #include <linux/timer.h>
> #include <linux/linkage.h>
>+#include <linux/bitops.h>
> 
> struct workqueue_struct;
> 
>@@ -75,8 +76,12 @@ extern void init_workqueues(void);
>  */
> static inline int cancel_delayed_work(struct work_struct *work)
> {
>-	return del_timer_sync(&work->timer);
>+	int ret;
>+
>+	ret = del_timer_sync(&work->timer);
>+	if (ret)
>+		clear_bit(0, &work->pending);
>+	return ret;
> }
> 
> #endif
>-
>
>_
>
>-
>To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at  http://vger.kernel.org/majordomo-info.html
>Please read the FAQ at  http://www.tux.org/lkml/
>  
>


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

end of thread, other threads:[~2004-05-04 13:35 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-05-03 11:39 workqueue and pending Mikkel Christiansen
2004-05-03 23:27 ` Andrew Morton
2004-05-04  2:51   ` Benjamin Herrenschmidt
2004-05-04  3:16     ` Andrew Morton
2004-05-04  3:55       ` Benjamin Herrenschmidt
2004-05-04  4:15         ` Andrew Morton
2004-05-04  4:41           ` Benjamin Herrenschmidt
2004-05-04 13:36       ` Mikkel Christiansen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox