aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-01-24 14:01:33 -0500
committerTejun Heo <tj@kernel.org>2013-01-24 14:01:33 -0500
commit715b06b864c99a18cb8368dfb187da4f569788cd (patch)
tree599ab1152a1c93b83d1be05aaeb370cac2e7e3eb
parent35b6bb63b8a288f90e07948867941a553b3d97bc (diff)
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: Tejun Heo <tj@kernel.org> Reviewed-by: Lai Jiangshan <laijs@cn.fujitsu.com>
-rw-r--r--include/linux/workqueue.h10
-rw-r--r--kernel/workqueue.c4
2 files changed, 11 insertions, 3 deletions
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index ff68b1d95b41..f8b35763e55f 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -73,13 +73,21 @@ enum {
73 73
74 WORK_OFFQ_CANCELING = (1 << WORK_OFFQ_FLAG_BASE), 74 WORK_OFFQ_CANCELING = (1 << WORK_OFFQ_FLAG_BASE),
75 75
76 /*
77 * When a work item is off queue, its high bits point to the last
78 * cpu it was on. Cap at 31 bits and use the highest number to
79 * indicate that no cpu is associated.
80 */
76 WORK_OFFQ_FLAG_BITS = 1, 81 WORK_OFFQ_FLAG_BITS = 1,
77 WORK_OFFQ_CPU_SHIFT = WORK_OFFQ_FLAG_BASE + WORK_OFFQ_FLAG_BITS, 82 WORK_OFFQ_CPU_SHIFT = WORK_OFFQ_FLAG_BASE + WORK_OFFQ_FLAG_BITS,
83 WORK_OFFQ_LEFT = BITS_PER_LONG - WORK_OFFQ_CPU_SHIFT,
84 WORK_OFFQ_CPU_BITS = WORK_OFFQ_LEFT <= 31 ? WORK_OFFQ_LEFT : 31,
85 WORK_OFFQ_CPU_NONE = (1LU << WORK_OFFQ_CPU_BITS) - 1,
78 86
79 /* convenience constants */ 87 /* convenience constants */
80 WORK_STRUCT_FLAG_MASK = (1UL << WORK_STRUCT_FLAG_BITS) - 1, 88 WORK_STRUCT_FLAG_MASK = (1UL << WORK_STRUCT_FLAG_BITS) - 1,
81 WORK_STRUCT_WQ_DATA_MASK = ~WORK_STRUCT_FLAG_MASK, 89 WORK_STRUCT_WQ_DATA_MASK = ~WORK_STRUCT_FLAG_MASK,
82 WORK_STRUCT_NO_CPU = (unsigned long)WORK_CPU_NONE << WORK_OFFQ_CPU_SHIFT, 90 WORK_STRUCT_NO_CPU = (unsigned long)WORK_OFFQ_CPU_NONE << WORK_OFFQ_CPU_SHIFT,
83 91
84 /* bit mask for work_busy() return values */ 92 /* bit mask for work_busy() return values */
85 WORK_BUSY_PENDING = 1 << 0, 93 WORK_BUSY_PENDING = 1 << 0,
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 1a686e481132..405282d30046 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -573,7 +573,7 @@ static struct global_cwq *get_work_gcwq(struct work_struct *work)
573 (data & WORK_STRUCT_WQ_DATA_MASK))->pool->gcwq; 573 (data & WORK_STRUCT_WQ_DATA_MASK))->pool->gcwq;
574 574
575 cpu = data >> WORK_OFFQ_CPU_SHIFT; 575 cpu = data >> WORK_OFFQ_CPU_SHIFT;
576 if (cpu == WORK_CPU_NONE) 576 if (cpu == WORK_OFFQ_CPU_NONE)
577 return NULL; 577 return NULL;
578 578
579 BUG_ON(cpu >= nr_cpu_ids && cpu != WORK_CPU_UNBOUND); 579 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)
583static void mark_work_canceling(struct work_struct *work) 583static void mark_work_canceling(struct work_struct *work)
584{ 584{
585 struct global_cwq *gcwq = get_work_gcwq(work); 585 struct global_cwq *gcwq = get_work_gcwq(work);
586 unsigned long cpu = gcwq ? gcwq->cpu : WORK_CPU_NONE; 586 unsigned long cpu = gcwq ? gcwq->cpu : WORK_OFFQ_CPU_NONE;
587 587
588 set_work_data(work, (cpu << WORK_OFFQ_CPU_SHIFT) | WORK_OFFQ_CANCELING, 588 set_work_data(work, (cpu << WORK_OFFQ_CPU_SHIFT) | WORK_OFFQ_CANCELING,
589 WORK_STRUCT_PENDING); 589 WORK_STRUCT_PENDING);