Commit 715b06b8 authored by Tejun Heo's avatar Tejun Heo

workqueue: introduce WORK_OFFQ_CPU_NONE

Currently, when a work item is off queue, high bits of its data
encodes the last CPU it was on.  This is scheduled to be changed to
pool ID, which will make it impossible to use WORK_CPU_NONE to
indicate no association.

This patch limits the number of bits which are used for off-queue cpu
number to 31 (so that the max fits in an int) and uses the highest
possible value - WORK_OFFQ_CPU_NONE - to indicate no association.
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Reviewed-by: default avatarLai Jiangshan <laijs@cn.fujitsu.com>
parent 35b6bb63
...@@ -73,13 +73,21 @@ enum { ...@@ -73,13 +73,21 @@ enum {
WORK_OFFQ_CANCELING = (1 << WORK_OFFQ_FLAG_BASE), WORK_OFFQ_CANCELING = (1 << WORK_OFFQ_FLAG_BASE),
/*
* When a work item is off queue, its high bits point to the last
* cpu it was on. Cap at 31 bits and use the highest number to
* indicate that no cpu is associated.
*/
WORK_OFFQ_FLAG_BITS = 1, WORK_OFFQ_FLAG_BITS = 1,
WORK_OFFQ_CPU_SHIFT = WORK_OFFQ_FLAG_BASE + WORK_OFFQ_FLAG_BITS, WORK_OFFQ_CPU_SHIFT = WORK_OFFQ_FLAG_BASE + WORK_OFFQ_FLAG_BITS,
WORK_OFFQ_LEFT = BITS_PER_LONG - WORK_OFFQ_CPU_SHIFT,
WORK_OFFQ_CPU_BITS = WORK_OFFQ_LEFT <= 31 ? WORK_OFFQ_LEFT : 31,
WORK_OFFQ_CPU_NONE = (1LU << WORK_OFFQ_CPU_BITS) - 1,
/* convenience constants */ /* convenience constants */
WORK_STRUCT_FLAG_MASK = (1UL << WORK_STRUCT_FLAG_BITS) - 1, WORK_STRUCT_FLAG_MASK = (1UL << WORK_STRUCT_FLAG_BITS) - 1,
WORK_STRUCT_WQ_DATA_MASK = ~WORK_STRUCT_FLAG_MASK, WORK_STRUCT_WQ_DATA_MASK = ~WORK_STRUCT_FLAG_MASK,
WORK_STRUCT_NO_CPU = (unsigned long)WORK_CPU_NONE << WORK_OFFQ_CPU_SHIFT, WORK_STRUCT_NO_CPU = (unsigned long)WORK_OFFQ_CPU_NONE << WORK_OFFQ_CPU_SHIFT,
/* bit mask for work_busy() return values */ /* bit mask for work_busy() return values */
WORK_BUSY_PENDING = 1 << 0, WORK_BUSY_PENDING = 1 << 0,
......
...@@ -573,7 +573,7 @@ static struct global_cwq *get_work_gcwq(struct work_struct *work) ...@@ -573,7 +573,7 @@ static struct global_cwq *get_work_gcwq(struct work_struct *work)
(data & WORK_STRUCT_WQ_DATA_MASK))->pool->gcwq; (data & WORK_STRUCT_WQ_DATA_MASK))->pool->gcwq;
cpu = data >> WORK_OFFQ_CPU_SHIFT; cpu = data >> WORK_OFFQ_CPU_SHIFT;
if (cpu == WORK_CPU_NONE) if (cpu == WORK_OFFQ_CPU_NONE)
return NULL; return NULL;
BUG_ON(cpu >= nr_cpu_ids && cpu != WORK_CPU_UNBOUND); BUG_ON(cpu >= nr_cpu_ids && cpu != WORK_CPU_UNBOUND);
...@@ -583,7 +583,7 @@ static struct global_cwq *get_work_gcwq(struct work_struct *work) ...@@ -583,7 +583,7 @@ static struct global_cwq *get_work_gcwq(struct work_struct *work)
static void mark_work_canceling(struct work_struct *work) static void mark_work_canceling(struct work_struct *work)
{ {
struct global_cwq *gcwq = get_work_gcwq(work); struct global_cwq *gcwq = get_work_gcwq(work);
unsigned long cpu = gcwq ? gcwq->cpu : WORK_CPU_NONE; unsigned long cpu = gcwq ? gcwq->cpu : WORK_OFFQ_CPU_NONE;
set_work_data(work, (cpu << WORK_OFFQ_CPU_SHIFT) | WORK_OFFQ_CANCELING, set_work_data(work, (cpu << WORK_OFFQ_CPU_SHIFT) | WORK_OFFQ_CANCELING,
WORK_STRUCT_PENDING); WORK_STRUCT_PENDING);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment