From: James Bottomley <James.Bottomley@SteelEye.com>
To: Linux Kernel <linux-kernel@vger.kernel.org>
Cc: mingo@elte.hu
Subject: [PATCH] add unschedule_delayed_work to the workqueue API
Date: 18 Oct 2004 11:31:00 -0500 [thread overview]
Message-ID: <1098117067.2011.64.camel@mulgrave> (raw)
I'm in the process of moving some of our scsi timers which do more work
than just a few lines of code into schedule_work() instead. The problem
is that the workqueue API lacks the equivalent of del_timer_sync().
This patch adds it as unschedule_delayed_work() (and also adds the
unschedule_work() API---it's probably much less useful, but
unschedule_delayed_work() is best constructed on top of it).
The idea is that unschedule_delayed_work() will return 0 if the work has
already executed and 1 if it hasn't. It is guaranteed that either the
work was removed or has been executed by the time
unschedule_delayed_work() returns (and thus it needs process context to
wait for the work function if necessary).
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
James
===== include/linux/workqueue.h 1.9 vs edited =====
--- 1.9/include/linux/workqueue.h 2004-08-23 03:14:58 -05:00
+++ edited/include/linux/workqueue.h 2004-10-18 10:01:54 -05:00
@@ -69,6 +69,11 @@
extern int current_is_keventd(void);
extern int keventd_up(void);
+extern int remove_work(struct workqueue_struct *wq, struct work_struct *work);
+extern int remove_delayed_work(struct workqueue_struct *wq, struct work_struct *work);
+extern int unschedule_work(struct work_struct *work);
+extern int unschedule_delayed_work(struct work_struct *work);
+
extern void init_workqueues(void);
/*
===== kernel/workqueue.c 1.28 vs edited =====
--- 1.28/kernel/workqueue.c 2004-09-08 01:33:10 -05:00
+++ edited/kernel/workqueue.c 2004-10-18 09:55:09 -05:00
@@ -81,6 +81,7 @@
spin_lock_irqsave(&cwq->lock, flags);
work->wq_data = cwq;
+ clear_bit(1, &work->pending);
list_add_tail(&work->entry, &cwq->worklist);
cwq->insert_sequence++;
wake_up(&cwq->more_work);
@@ -170,6 +171,7 @@
BUG_ON(work->wq_data != cwq);
clear_bit(0, &work->pending);
f(data);
+ set_bit(1, &work->pending);
spin_lock_irqsave(&cwq->lock, flags);
cwq->remove_sequence++;
@@ -517,13 +519,94 @@
BUG_ON(!keventd_wq);
}
+/**
+ * remove_work - try to remove a piece of queued work from a workqueue
+ * @wq: the workqueue to remove it from
+ * @work: the item of work queued on the workqueue
+ *
+ * Tries to remove the work before it is executed. Guarantees that
+ * when it returns either the work is removed or it has been executed.
+ * Requires process context since it may sleep if the work function is
+ * executing.
+ *
+ * Returns 1 if work was successfully removed without executing and 0
+ * if the work was executed.
+ */
+int remove_work(struct workqueue_struct *wq, struct work_struct *work)
+{
+ int ret = 1, cpu = get_cpu();
+ struct cpu_workqueue_struct *cwq;
+ unsigned long flags;
+
+ if (unlikely(is_single_threaded(wq)))
+ cpu = 0;
+
+ cwq = &wq->cpu_wq[cpu];
+
+ spin_lock_irqsave(&cwq->lock, flags);
+ list_del_init(&work->entry);
+ if (test_and_clear_bit(0, &work->pending))
+ goto out_unlock;
+ /* work is not pending. It has either executed or is in the
+ * process of executing */
+ ret = 0;
+ while (!test_bit(1, &work->pending)) {
+ DEFINE_WAIT(wait);
+ prepare_to_wait(&cwq->work_done, &wait,
+ TASK_UNINTERRUPTIBLE);
+ spin_unlock_irq(&cwq->lock);
+ schedule();
+ spin_lock_irq(&cwq->lock);
+ finish_wait(&cwq->work_done, &wait);
+ }
+
+ out_unlock:
+ spin_unlock_irqrestore(&cwq->lock, flags);
+
+ put_cpu();
+ return ret;
+}
+
+/**
+ * remove_delayed_work - try to remove a piece of queued work from a workqueue
+ * @wq: the workqueue to remove it from
+ * @work: the item of work queued on the workqueue
+ *
+ * Tries to remove the work before it is executed. Guarantees that
+ * when it returns either the work is removed or it has been executed.
+ * Requires process context since it may sleep if the work function is
+ * executing.
+ *
+ * Returns 1 if work was successfully removed without executing and 0
+ * if the work was executed.
+ */
+int remove_delayed_work(struct workqueue_struct *wq, struct work_struct *work)
+{
+ if (del_timer_sync(&work->timer))
+ return 1;
+ return remove_work(wq, work);
+}
+
+int unschedule_work(struct work_struct *work)
+{
+ return remove_work(keventd_wq, work);
+}
+
+int unschedule_delayed_work(struct work_struct *work)
+{
+ return remove_delayed_work(keventd_wq, work);
+}
+
EXPORT_SYMBOL_GPL(__create_workqueue);
EXPORT_SYMBOL_GPL(queue_work);
EXPORT_SYMBOL_GPL(queue_delayed_work);
EXPORT_SYMBOL_GPL(flush_workqueue);
EXPORT_SYMBOL_GPL(destroy_workqueue);
+EXPORT_SYMBOL_GPL(remove_work);
EXPORT_SYMBOL(schedule_work);
EXPORT_SYMBOL(schedule_delayed_work);
EXPORT_SYMBOL(schedule_delayed_work_on);
EXPORT_SYMBOL(flush_scheduled_work);
+EXPORT_SYMBOL(unschedule_work);
+EXPORT_SYMBOL(unschedule_delayed_work);
next reply other threads:[~2004-10-18 16:31 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-10-18 16:31 James Bottomley [this message]
2004-10-18 21:25 ` [PATCH] add unschedule_delayed_work to the workqueue API Andrew Morton
2004-10-18 21:26 ` James Bottomley
2004-10-18 21:29 ` James Bottomley
2004-10-18 21:43 ` Andrew Morton
2004-10-18 21:47 ` James Bottomley
2004-10-18 22:02 ` Andrew Morton
2004-10-18 22:15 ` James Bottomley
2004-10-18 22:57 ` Andrew Morton
2004-10-18 23:24 ` James Bottomley
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1098117067.2011.64.camel@mulgrave \
--to=james.bottomley@steeleye.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.