Skip to content

Commit f09b10b

Browse files
committed
workqueue: Remove WORK_OFFQ_CANCELING
cancel[_delayed]_work_sync() guarantees that it can shut down self-requeueing work items. To achieve that, it grabs and then holds WORK_STRUCT_PENDING bit set while flushing the currently executing instance. As the PENDING bit is set, all queueing attempts including the self-requeueing ones fail and once the currently executing instance is flushed, the work item should be idle as long as someone else isn't actively queueing it. This means that the cancel_work_sync path may hold the PENDING bit set while flushing the target work item. This isn't a problem for the queueing path - it can just fail which is the desired effect. It doesn't affect flush. It doesn't matter to cancel_work either as it can just report that the work item has successfully canceled. However, if there's another cancel_work_sync attempt on the work item, it can't simply fail or report success and that would breach the guarantee that it should provide. cancel_work_sync has to wait for and grab that PENDING bit and go through the motions. WORK_OFFQ_CANCELING and wq_cancel_waitq are what implement this cancel_work_sync to cancel_work_sync wait mechanism. When a work item is being canceled, WORK_OFFQ_CANCELING is also set on it and other cancel_work_sync attempts wait on the bit to be cleared using the wait queue. While this works, it's an isolated wart which doesn't jive with the rest of flush and cancel mechanisms and forces enable_work() and disable_work() to require a sleepable context, which hampers their usability. Now that a work item can be disabled, we can use that to block queueing while cancel_work_sync is in progress. Instead of holding PENDING the bit, it can temporarily disable the work item, flush and then re-enable it as that'd achieve the same end result of blocking queueings while canceling and thus enable canceling of self-requeueing work items. - WORK_OFFQ_CANCELING and the surrounding mechanims are removed. - work_grab_pending() is now simpler, no longer has to wait for a blocking operation and thus can be called from any context. - With work_grab_pending() simplified, no need to use try_to_grab_pending() directly. All users are converted to use work_grab_pending(). - __cancel_work_sync() is updated to __cancel_work() with WORK_CANCEL_DISABLE to cancel and plug racing queueing attempts. It then flushes and re-enables the work item if necessary. - These changes allow disable_work() and enable_work() to be called from any context. v2: Lai pointed out that mod_delayed_work_on() needs to check the disable count before queueing the delayed work item. Added clear_pending_if_disabled() call. Signed-off-by: Tejun Heo <[email protected]> Reviewed-by: Lai Jiangshan <[email protected]>
1 parent 86898fa commit f09b10b

File tree

2 files changed

+20
-124
lines changed

2 files changed

+20
-124
lines changed

include/linux/workqueue.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,9 @@ enum work_bits {
5252
*
5353
* MSB
5454
* [ pool ID ] [ disable depth ] [ OFFQ flags ] [ STRUCT flags ]
55-
* 16 bits 1 bit 4 or 5 bits
55+
* 16 bits 0 bits 4 or 5 bits
5656
*/
5757
WORK_OFFQ_FLAG_SHIFT = WORK_STRUCT_FLAG_BITS,
58-
WORK_OFFQ_CANCELING_BIT = WORK_OFFQ_FLAG_SHIFT,
5958
WORK_OFFQ_FLAG_END,
6059
WORK_OFFQ_FLAG_BITS = WORK_OFFQ_FLAG_END - WORK_OFFQ_FLAG_SHIFT,
6160

@@ -99,7 +98,6 @@ enum wq_misc_consts {
9998
};
10099

101100
/* Convenience constants - of type 'unsigned long', not 'enum'! */
102-
#define WORK_OFFQ_CANCELING (1ul << WORK_OFFQ_CANCELING_BIT)
103101
#define WORK_OFFQ_FLAG_MASK (((1ul << WORK_OFFQ_FLAG_BITS) - 1) << WORK_OFFQ_FLAG_SHIFT)
104102
#define WORK_OFFQ_DISABLE_MASK (((1ul << WORK_OFFQ_DISABLE_BITS) - 1) << WORK_OFFQ_DISABLE_SHIFT)
105103
#define WORK_OFFQ_POOL_NONE ((1ul << WORK_OFFQ_POOL_BITS) - 1)

kernel/workqueue.c

Lines changed: 19 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -496,12 +496,6 @@ static struct workqueue_attrs *unbound_std_wq_attrs[NR_STD_WORKER_POOLS];
496496
/* I: attributes used when instantiating ordered pools on demand */
497497
static struct workqueue_attrs *ordered_wq_attrs[NR_STD_WORKER_POOLS];
498498

499-
/*
500-
* Used to synchronize multiple cancel_sync attempts on the same work item. See
501-
* work_grab_pending() and __cancel_work_sync().
502-
*/
503-
static DECLARE_WAIT_QUEUE_HEAD(wq_cancel_waitq);
504-
505499
/*
506500
* I: kthread_worker to release pwq's. pwq release needs to be bounced to a
507501
* process context while holding a pool lock. Bounce to a dedicated kthread
@@ -783,11 +777,6 @@ static int work_next_color(int color)
783777
* corresponding to a work. Pool is available once the work has been
784778
* queued anywhere after initialization until it is sync canceled. pwq is
785779
* available only while the work item is queued.
786-
*
787-
* %WORK_OFFQ_CANCELING is used to mark a work item which is being
788-
* canceled. While being canceled, a work item may have its PENDING set
789-
* but stay off timer and worklist for arbitrarily long and nobody should
790-
* try to steal the PENDING bit.
791780
*/
792781
static inline void set_work_data(struct work_struct *work, unsigned long data)
793782
{
@@ -921,13 +910,6 @@ static unsigned long work_offqd_pack_flags(struct work_offq_data *offqd)
921910
((unsigned long)offqd->flags);
922911
}
923912

924-
static bool work_is_canceling(struct work_struct *work)
925-
{
926-
unsigned long data = atomic_long_read(&work->data);
927-
928-
return !(data & WORK_STRUCT_PWQ) && (data & WORK_OFFQ_CANCELING);
929-
}
930-
931913
/*
932914
* Policy functions. These define the policies on how the global worker
933915
* pools are managed. Unless noted otherwise, these functions assume that
@@ -2058,8 +2040,6 @@ static void pwq_dec_nr_in_flight(struct pool_workqueue *pwq, unsigned long work_
20582040
* 1 if @work was pending and we successfully stole PENDING
20592041
* 0 if @work was idle and we claimed PENDING
20602042
* -EAGAIN if PENDING couldn't be grabbed at the moment, safe to busy-retry
2061-
* -ENOENT if someone else is canceling @work, this state may persist
2062-
* for arbitrarily long
20632043
* ======== ================================================================
20642044
*
20652045
* Note:
@@ -2155,26 +2135,9 @@ static int try_to_grab_pending(struct work_struct *work, u32 cflags,
21552135
fail:
21562136
rcu_read_unlock();
21572137
local_irq_restore(*irq_flags);
2158-
if (work_is_canceling(work))
2159-
return -ENOENT;
2160-
cpu_relax();
21612138
return -EAGAIN;
21622139
}
21632140

2164-
struct cwt_wait {
2165-
wait_queue_entry_t wait;
2166-
struct work_struct *work;
2167-
};
2168-
2169-
static int cwt_wakefn(wait_queue_entry_t *wait, unsigned mode, int sync, void *key)
2170-
{
2171-
struct cwt_wait *cwait = container_of(wait, struct cwt_wait, wait);
2172-
2173-
if (cwait->work != key)
2174-
return 0;
2175-
return autoremove_wake_function(wait, mode, sync, key);
2176-
}
2177-
21782141
/**
21792142
* work_grab_pending - steal work item from worklist and disable irq
21802143
* @work: work item to steal
@@ -2184,7 +2147,7 @@ static int cwt_wakefn(wait_queue_entry_t *wait, unsigned mode, int sync, void *k
21842147
* Grab PENDING bit of @work. @work can be in any stable state - idle, on timer
21852148
* or on worklist.
21862149
*
2187-
* Must be called in process context. IRQ is disabled on return with IRQ state
2150+
* Can be called from any context. IRQ is disabled on return with IRQ state
21882151
* stored in *@irq_flags. The caller is responsible for re-enabling it using
21892152
* local_irq_restore().
21902153
*
@@ -2193,41 +2156,14 @@ static int cwt_wakefn(wait_queue_entry_t *wait, unsigned mode, int sync, void *k
21932156
static bool work_grab_pending(struct work_struct *work, u32 cflags,
21942157
unsigned long *irq_flags)
21952158
{
2196-
struct cwt_wait cwait;
21972159
int ret;
21982160

2199-
might_sleep();
2200-
repeat:
2201-
ret = try_to_grab_pending(work, cflags, irq_flags);
2202-
if (likely(ret >= 0))
2203-
return ret;
2204-
if (ret != -ENOENT)
2205-
goto repeat;
2206-
2207-
/*
2208-
* Someone is already canceling. Wait for it to finish. flush_work()
2209-
* doesn't work for PREEMPT_NONE because we may get woken up between
2210-
* @work's completion and the other canceling task resuming and clearing
2211-
* CANCELING - flush_work() will return false immediately as @work is no
2212-
* longer busy, try_to_grab_pending() will return -ENOENT as @work is
2213-
* still being canceled and the other canceling task won't be able to
2214-
* clear CANCELING as we're hogging the CPU.
2215-
*
2216-
* Let's wait for completion using a waitqueue. As this may lead to the
2217-
* thundering herd problem, use a custom wake function which matches
2218-
* @work along with exclusive wait and wakeup.
2219-
*/
2220-
init_wait(&cwait.wait);
2221-
cwait.wait.func = cwt_wakefn;
2222-
cwait.work = work;
2223-
2224-
prepare_to_wait_exclusive(&wq_cancel_waitq, &cwait.wait,
2225-
TASK_UNINTERRUPTIBLE);
2226-
if (work_is_canceling(work))
2227-
schedule();
2228-
finish_wait(&wq_cancel_waitq, &cwait.wait);
2229-
2230-
goto repeat;
2161+
while (true) {
2162+
ret = try_to_grab_pending(work, cflags, irq_flags);
2163+
if (ret >= 0)
2164+
return ret;
2165+
cpu_relax();
2166+
}
22312167
}
22322168

22332169
/**
@@ -2645,19 +2581,14 @@ bool mod_delayed_work_on(int cpu, struct workqueue_struct *wq,
26452581
struct delayed_work *dwork, unsigned long delay)
26462582
{
26472583
unsigned long irq_flags;
2648-
int ret;
2584+
bool ret;
26492585

2650-
do {
2651-
ret = try_to_grab_pending(&dwork->work, WORK_CANCEL_DELAYED,
2652-
&irq_flags);
2653-
} while (unlikely(ret == -EAGAIN));
2586+
ret = work_grab_pending(&dwork->work, WORK_CANCEL_DELAYED, &irq_flags);
26542587

2655-
if (likely(ret >= 0)) {
2588+
if (!clear_pending_if_disabled(&dwork->work))
26562589
__queue_delayed_work(cpu, wq, dwork, delay);
2657-
local_irq_restore(irq_flags);
2658-
}
26592590

2660-
/* -ENOENT from try_to_grab_pending() becomes %true */
2591+
local_irq_restore(irq_flags);
26612592
return ret;
26622593
}
26632594
EXPORT_SYMBOL_GPL(mod_delayed_work_on);
@@ -4320,16 +4251,7 @@ static bool __cancel_work(struct work_struct *work, u32 cflags)
43204251
unsigned long irq_flags;
43214252
int ret;
43224253

4323-
if (cflags & WORK_CANCEL_DISABLE) {
4324-
ret = work_grab_pending(work, cflags, &irq_flags);
4325-
} else {
4326-
do {
4327-
ret = try_to_grab_pending(work, cflags, &irq_flags);
4328-
} while (unlikely(ret == -EAGAIN));
4329-
4330-
if (unlikely(ret < 0))
4331-
return false;
4332-
}
4254+
ret = work_grab_pending(work, cflags, &irq_flags);
43334255

43344256
work_offqd_unpack(&offqd, *work_data_bits(work));
43354257

@@ -4344,22 +4266,9 @@ static bool __cancel_work(struct work_struct *work, u32 cflags)
43444266

43454267
static bool __cancel_work_sync(struct work_struct *work, u32 cflags)
43464268
{
4347-
struct work_offq_data offqd;
4348-
unsigned long irq_flags;
43494269
bool ret;
43504270

4351-
/* claim @work and tell other tasks trying to grab @work to back off */
4352-
ret = work_grab_pending(work, cflags, &irq_flags);
4353-
4354-
work_offqd_unpack(&offqd, *work_data_bits(work));
4355-
4356-
if (cflags & WORK_CANCEL_DISABLE)
4357-
work_offqd_disable(&offqd);
4358-
4359-
offqd.flags |= WORK_OFFQ_CANCELING;
4360-
set_work_pool_and_keep_pending(work, offqd.pool_id,
4361-
work_offqd_pack_flags(&offqd));
4362-
local_irq_restore(irq_flags);
4271+
ret = __cancel_work(work, cflags | WORK_CANCEL_DISABLE);
43634272

43644273
/*
43654274
* Skip __flush_work() during early boot when we know that @work isn't
@@ -4368,19 +4277,8 @@ static bool __cancel_work_sync(struct work_struct *work, u32 cflags)
43684277
if (wq_online)
43694278
__flush_work(work, true);
43704279

4371-
work_offqd_unpack(&offqd, *work_data_bits(work));
4372-
4373-
/*
4374-
* smp_mb() at the end of set_work_pool_and_clear_pending() is paired
4375-
* with prepare_to_wait() above so that either waitqueue_active() is
4376-
* visible here or !work_is_canceling() is visible there.
4377-
*/
4378-
offqd.flags &= ~WORK_OFFQ_CANCELING;
4379-
set_work_pool_and_clear_pending(work, WORK_OFFQ_POOL_NONE,
4380-
work_offqd_pack_flags(&offqd));
4381-
4382-
if (waitqueue_active(&wq_cancel_waitq))
4383-
__wake_up(&wq_cancel_waitq, TASK_NORMAL, 1, work);
4280+
if (!(cflags & WORK_CANCEL_DISABLE))
4281+
enable_work(work);
43844282

43854283
return ret;
43864284
}
@@ -4464,8 +4362,8 @@ EXPORT_SYMBOL(cancel_delayed_work_sync);
44644362
* will fail and return %false. The maximum supported disable depth is 2 to the
44654363
* power of %WORK_OFFQ_DISABLE_BITS, currently 65536.
44664364
*
4467-
* Must be called from a sleepable context. Returns %true if @work was pending,
4468-
* %false otherwise.
4365+
* Can be called from any context. Returns %true if @work was pending, %false
4366+
* otherwise.
44694367
*/
44704368
bool disable_work(struct work_struct *work)
44714369
{
@@ -4496,8 +4394,8 @@ EXPORT_SYMBOL_GPL(disable_work_sync);
44964394
* Undo disable_work[_sync]() by decrementing @work's disable count. @work can
44974395
* only be queued if its disable count is 0.
44984396
*
4499-
* Must be called from a sleepable context. Returns %true if the disable count
4500-
* reached 0. Otherwise, %false.
4397+
* Can be called from any context. Returns %true if the disable count reached 0.
4398+
* Otherwise, %false.
45014399
*/
45024400
bool enable_work(struct work_struct *work)
45034401
{

0 commit comments

Comments
 (0)